Ce document est une traduction de la recommandation XML Schema du W3C, datée du 2 mai 2001. Cette version traduite peut contenir des erreurs absentes de l'original, introduites par la traduction elle-même. La version originale en anglais, seule normative, se trouve à l'adresse http://www.w3.org/TR/2001/REC-xmlschema-0-20010502/.

Traduction :

Copyright © 1998 W3C (MIT, INRIA, Keio), tous droits réservés. Les règles du W3C sur la responsabilité, les marques commerciales, les droits des auteurs et les licences des logiciels sont applicables.

Remarque de la traduction: L'entité caractère nécessaire au "oe" ligaturé n'étant pas supportée par certains navigateurs, ce caractère sera écrit oe.



 

W3C

XML Schema tome 0 : Introduction

Recommandation du W3C du 2 Mai 2001

Cette version :
http://www.w3.org/TR/2001/REC-xmlschema-0-20010502/
Dernière version :
http://www.w3.org/TR/xmlschema-0/
Version précédente :
http://www.w3.org/TR/2001/PR-xmlschema-0-20010330/
Editeur :
David C. Fallside (IBM) fallside@us.ibm.com

Résumé

Le tome 0 de la spécification XML Schema n'est qu'une introduction et n'est pas un document normatif. Son objectif est de fournir un texte facilement compréhensible des fonctions offertes par XML Schema pour comprendre comment créer des schémas avec le langage XML Schema. Les documents normatifs XML Schema tome 1 : Structures et XML Schema tome 2 : Types de données contiennent une description complète et formelle de la norme. Dans cette introduction, les fonctions du langage sont décrites au travers d'un grand nombre d'exemples complétés par des renvois au texte normatif.

Statut de ce document

Ce chapitre décrit le statut de ce document au moment de sa publication. D'autres documents peuvent être plus récents que celui-ci. Le dernier statut en date de ce document est tenu à jour par le w3c.

Ce document a été contrôlé par les personnes concernées par le sujet, membres du W3C et autres, et a été validé par le directeur du W3C en tant que recommandation. Il s'agit donc d'un document stable qui peut être utilisé comme document de référence. Le rôle des recommandations du W3C est d'attirer l'attention sur la spécification et d'en promouvoir largement le déploiement. Cela dans le but d'améliorer le fonctionnement et l'interopérabilité du Web.

Ce document a été produit par le groupe de travail sur XML Schema au titre de l'activité XML du W3C. Les objectifs du langage XML Schema sont présentés dans le document de spécification de XML Schema. Les auteurs de ce document sont les membres du groupe de travail sur XML Schema. Les différents tomes ont chacun leurs propres éditeurs.

Cette version intègre les remarques correctives faites sur les versions antérieures.

Vous voudrez bien faire remonter les erreurs trouvées dans ce document à www-xml-schema-comments@w3.org (archive) (ou directement à la traduction française mentionnée en début de document) La liste des erreurs connues de la version anglaise de cette spécification est disponible à l'adresse http://www.w3.org/2001/05/xmlschema-errata.

La version anglaise de cette spécification est la seule version normative du présent document. Les informations concernant ses traductions sont disponibles à l'adresse http://www.w3.org/2001/05/xmlschema-translations.

Une liste complète des recommandations actuelles du W3C et d'autres documents techniques peuvent être trouvés à l'adresse http://www.w3.org/TR/.

Table des matières

1 Introduction
2 Concepts de base : un bon de commande
 2.1 Schéma d'un bon de commande
 2.2 Définitions de types complexes, les déclarations d'éléments et d'attributs
  2.2.1 Contraintes d'occurrence
  2.2.2 Eléments et attributs globaux
  2.2.3 Conflits de nommage
 2.3 Types simples
  2.3.1 Types de listes
  2.3.2 Types union
 2.4 Définition du type anonyme
 2.5 Contenu d'un élément
  2.5.1 Types complexes dérivés de types simples
  2.5.2 Contenu mixte
  2.5.3 Contenu vide
  2.5.4 Contenu libre
 2.6 Annotations
 2.7 Construction de modèles de contenu
 2.8 Groupes d'attributs
 2.9 Valeurs Nil
3 Concepts avancés I : espaces de noms, schémas et qualification
 3.1 Espaces de noms cibles et noms locaux non-qualifiés
 3.2 Noms locaux qualifiés
 3.3 Déclarations globales versus locales
 3.4 Espaces de noms cibles non-déclarés
4 Concepts avancés II : un bon de commande international
 4.1 Un schéma réparti entre plusieurs documents
 4.2 Dérivation de types par extension
 4.3 Utilisation de types dérivés dans des instances de documents
 4.4 Dérivation de types complexes par restriction
 4.5 Redéfinition de types et de groupes
 4.6 Groupes de substitution
 4.7 Eléments et types abstraits
 4.8 Contrôler la création et l'utilisation de types dérivés
5 Concepts avancés III : un rapport trimestriel
 5.1 Spécification d'unicité
 5.2 Définition des clés et de leurs références
 5.3 Contraintes de XML Schema versus les attributs ID de XML 1.0
 5.4 Importation de types
  5.4.1 Bibliothèques de types
 5.5 Eléments et attributs any
 5.6 attribut schemaLocation
 5.7 Conformité

Annexes

A Remerciements
B Types simples et leurs facettes
C Utilisation des entités
D Expressions régulières
E Index

1 Introduction

Ce document, XML Schema tome 0 : introduction, est une description simplifiée du langage de définition des schémas XML qui doit être utilisée parallèlement à la description formelle qui en est faite dans les tomes 1 (Structures) et 2 (Types de données). Les lecteurs supposés de ce document sont les développeurs d'applications amenés à écrire des programmes lisant ou écrivant des documents de type schéma ainsi que les auteurs de schémas qui ont besoin de connaître les fonctionnalités offertes par le langage, en particulier celles qui sont nouvelles par rapport à celles disponibles avec les DTD. Le texte suppose que vous ayez une connaissance de base de XML 1.0 et de XML-Namespaces. Chaque chapitre de cette introduction à XML Schema traite des nouvelles fonctionnalités du langage en s'appuyant sur des cas concrets.

Le chapitre 2 couvre les mécanismes de base de XML Schema. Il aborde les sujets suivants : la déclaration des éléments et des attributs destinés à être utilisés dans des documents XML, les différences entre les types simples et complexes, la manière de définir des types complexes, l'utilisation des types simples comme valeurs d'éléments et d'attributs, l'annotation des schémas, la présentation d'un mécanisme simple de réutilisation des définitions d'éléments et d'attributs et les valeurs nulles.

Le chapitre 3, le premier des chapitres avancés de cette introduction, concerne les concepts élémentaires régissant l'utilisation des espaces de noms dans les schémas XML et les documents. Ce chapitre est important pour comprendre la plupart des sujets qui sont abordés dans les chapitres avancés II et III.

Le chapitre 4, le deuxième des chapitres avancés de cette introduction, décrit les mécanismes de dérivation des types à partir des types fournis par XML Schema et de contrôle de ces dérivations. Le chapitre décrit aussi les mécanismes de fusion de fragments de schéma issus de plusieurs sources et de substitution d'éléments.

Le chapitre 5 couvre des mécanismes encore plus avancés, comprenant un mécanisme de spécification de l'unicité de certains attributs ou éléments, un mécanisme d'utilisation des types à travers plusieurs espaces de noms, un mécanisme d'extension des types basés sur les espaces de noms et une description du mécanisme de contrôle de la conformité des documents.

En plus des chapitres qui viennent d'être décrits, l'introduction contient un certain nombre d'annexes qui fournissent des informations de référence précises sur les types simples et le langage des expressions régulières.

L'introduction n'est pas un document normatif, ce qui signifie qu'elle n'est pas une spécification définitive du langage XML Schema (du point de vue du W3C). Les exemples et autres supports des explications fournies dans ce document sont fournis pour vous aider à comprendre XML Schema, mais peuvent ne pas fournir de réponse définitive à vos questions. Dans ce cas, vous aurez besoin de vous reporter à la spécification de XML Schema, et pour vous aider à le faire, nous fournissons de nombreux liens vers les parties concernées des tomes 1 et 2 de la spécification. Plus précisément, les items de XML Schema mentionnés dans cette introduction sont reliés à un index des noms d'éléments et d'attributs ainsi qu'à un tableau résumé des types de données, tous les deux étant physiquement dans cette introduction. Le tableau et l'index contiennent des liens aux parties concernées des parties 1 et 2 de la spécification XML Schema.

2 Concepts de base : un bon de commande

L'objet de ce schéma est de définir une classe de documents XML : le terme d'instance de document est souvent utilisé pour désigner un fichier contenant un document XML conforme à un schéma particulier. En fait, ni les instances ni les schémas n'ont besoin d'exister physiquement sous la forme de documents stockés dans des fichiers -- ils peuvent exister en tant que flots de données échangés entre deux applications, des champs d'une base de données ou comme des collections d'ensembles d'informations, des "granules d'informations" -- mais pour simplifier cette introduction, nous avons choisi de ne faire référence qu'à des instances et des schémas considérés sous la forme de documents et de fichiers.

Commençons par considérer une instance de document dans un fichier appelé po.xml. Elle contient la description d'un bon de commande émis par une personne privée et une application de facturation :

Le bon de commande, fichier po.xml
<?xml version="1.0"?>
<purchaseOrder orderDate="1999-10-20">
    <shipTo country="US">
        <name>Alice Smith</name>
        <street>123 Maple Street</street>
        <city>Mill Valley</city>
        <state>CA</state>
        <zip>90952</zip>
    </shipTo>
    <billTo country="US">
        <name>Robert Smith</name>
        <street>8 Oak Avenue</street>
        <city>Old Town</city>
        <state>PA</state>
        <zip>95819</zip>
    </billTo>
    <comment>Hurry, my lawn is going wild!</comment>
    <items>
        <item partNum="872-AA">
            <productName>Lawnmower</productName>
            <quantity>1</quantity>
            <USPrice>148.95</USPrice>
            <comment>Confirm this est electric</comment>
        </item>
        <item partNum="926-AA">
            <productName>Baby Monitor</productName>
            <quantity>1</quantity>
            <USPrice>39.98</USPrice>
            <shipDate>1999-05-21</shipDate>
        </item>
    </items>
</purchaseOrder>

Le bon de commande est constitué d'un élément principal, purchaseOrder, et des sous-éléments shipTo, billTo, comment et items. Ceux-là (à l'exception de l'élément comment) contiennent à leur tour d'autres sous-éléments, et ainsi de suite, jusqu'à ce qu'un sous-élément comme par exemple USPrice contienne un nombre plutôt qu'un sous-élément. On dit que les éléments qui contiennent des sous-éléments ou portent des attributs sont de type complexe, tandis que les éléments qui contiennent des nombres (ou des chaînes de caractères, des dates, etc.) sans autre sous-élément sont de type simple. Quelques éléments ont des attributs ; les attributs sont toujours de type simple.

Dans une instance de document, les types complexes et une partie des types simples qui y sont utilisés sont définis dans le schéma associé. Les autres types simples sont ceux qui sont prédéfinis par XML Schema.

Avant d'aller plus en avant dans l'analyse du schéma des bons de commande, nous allons digresser momentanément pour parler de l'association entre une instance et le schéma du bon de commande. Comme vous pouvez vous en apercevoir en regardant une instance de document, le schéma du bon de commande n'est pas mentionné. Il n'est pas pour l'instant obligatoire que les instances référencent les schémas et même si cela sera fait dans de nombreux cas, nous avons choisi de simplifier ce premier chapitre et de considérer que n'importe quel programme de traitement de l'instance saura accéder au schéma correspondant sans avoir besoin que l'information soit écrite en dur dans l'instance. Dans les chapitres suivants, nous introduirons les mécanismes explicites qui permettent d'associer une instance à un schéma.

2.1 Schéma d'un bon de commande

Le schéma d'un bon de commande est contenu dans le fichier po.xsd:

Le schéma d'un bon de commande, po.xsd
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

 <xsd:annotation>
  <xsd:documentation xml:lang="en">
   Purchase order schema Par exemple.com.
   Copyright 2000 exemple.com. All rights reserved.
  </xsd:documentation>
 </xsd:annotation>

 <xsd:element name="purchaseOrder" type="PurchaseOrderType"/>

 <xsd:element name="comment" type="xsd:string"/>

 <xsd:complexType name="PurchaseOrderType">
  <xsd:sequence>
   <xsd:element name="shipTo" type="USAddress"/>
   <xsd:element name="billTo" type="USAddress"/>
   <xsd:element ref="comment" minOccurs="0"/>
   <xsd:element name="items"  type="Items"/>
  </xsd:sequence>
  <xsd:attribute name="orderDate" type="xsd:date"/>
 </xsd:complexType>

 <xsd:complexType name="USAddress">
  <xsd:sequence>
   <xsd:element name="name"   type="xsd:string"/>
   <xsd:element name="street" type="xsd:string"/>
   <xsd:element name="city"   type="xsd:string"/>
   <xsd:element name="state"  type="xsd:string"/>
   <xsd:element name="zip"    type="xsd:decimal"/>
  </xsd:sequence>
  <xsd:attribute name="country" type="xsd:NMTOKEN"
     fixed="US"/>
 </xsd:complexType>

 <xsd:complexType name="Items">
  <xsd:sequence>
   <xsd:element name="item" minOccurs="0" maxOccurs="unbounded">
    <xsd:complexType>
     <xsd:sequence>
      <xsd:element name="productName" type="xsd:string"/>
      <xsd:element name="quantity">
       <xsd:simpleType>
        <xsd:restriction base="xsd:positiveInteger">
         <xsd:maxExclusive value="100"/>
        </xsd:restriction>
       </xsd:simpleType>
      </xsd:element>
      <xsd:element name="USPrice"  type="xsd:decimal"/>
      <xsd:element ref="comment"   minOccurs="0"/>
      <xsd:element name="shipDate" type="xsd:date" minOccurs="0"/>
     </xsd:sequence>
     <xsd:attribute name="partNum" type="SKU" use="required"/>
    </xsd:complexType>
   </xsd:element>
  </xsd:sequence>
 </xsd:complexType>

 <!-- Stock Keeping Unit, one code for identifying products -->
 <xsd:simpleType name="SKU">
  <xsd:restriction base="xsd:string">
   <xsd:pattern value="\d{3}-[A-Z]{2}"/>
  </xsd:restriction>
 </xsd:simpleType>

</xsd:schema>

Le schéma des bons de commande est constitué d'un élément schema et d'une variété de sous-éléments, les principaux étant element, complexType, et simpleType qui déterminent l'ordre d'apparition des éléments dans l'instance et leurs types de contenu.

Chacun des éléments du schéma est préfixé par xsd: associé à l'espace de noms du schéma XML utilisé par le biais de la déclaration xmlns:xsd="http://www.w3.org/2001/XMLSchema" qui est un attribut de l'élément schema. Le préfixe xsd: est couramment utilisé pour identifier l'espace de noms des schémas XML alors que n'importe quelle valeur de préfixe pourrait, en réalité, être utilisée. Le même préfixe et par conséquence la même association, apparaît également sur les noms des types simples préconstruits, par exemple xsd:string. Dans ce cas, le but de cette association est d'affirmer que les éléments et les types simples ainsi préfixés appartiennent au vocabulaire du langage XML Schema et non au vocabulaire particulier de l'auteur du schéma. Pour la lisibilité du texte, nous ne faisons que mentionner les noms des éléments et des types simples (par exemple simpleType) en omettant leur préfixe.

2.2 Définitions de types complexes, les déclarations d'éléments et d'attributs

Dans XML Schema, il y un une différence de base entre les éléments de type complexe qui peuvent contenir des sous-éléments et être qualifiés par des attributs et ceux de type simple qui ne peuvent contenir ni sous-éléments ni être qualifiés par des attributs. Il y un également une distinction majeure entre les définitions qui servent à créer de nouveaux types (qu'ils soient de type simple ou complexe) et les déclarations qui servent à spécifier les noms et les types des éléments et attributs qui pourront être utilisés dans les instances de documents. Dans ce chapitre, nous nous concentrons sur les définitions de types complexes et les déclarations d'éléments et d'attributs qu'elles contiennent.

Les nouveaux types complexes sont créés en utilisant l'élément complexType composé, dans la plupart des cas, d'une série de déclarations d'éléments et d'attributs et de références d'éléments. Les déclarations ne sont pas elles mêmes des types mais plutôt des associations faites entre un nom et des contraintes qui régissent les règles d'apparition de l'élément dans une instance de document correspondant au schéma. Les éléments sont déclarés en utilisant l'élément element et les attributs sont déclarés en utilisant l'élément attribute. Par exemple, l'élément USAddress est défini comme étant de type complexe et, à l'intérieur de sa définition, nous remarquons la présence de cinq déclarations d'éléments et d'une déclaration d'attribut :

Définition du type USAddress
 <xsd:complexType name="USAddress" >
  <xsd:sequence>
   <xsd:element name="name"   type="xsd:string"/>
   <xsd:element name="street" type="xsd:string"/>
   <xsd:element name="city"   type="xsd:string"/>
   <xsd:element name="state"  type="xsd:string"/>
   <xsd:element name="zip"    type="xsd:decimal"/>
  </xsd:sequence>
  <xsd:attribute name="country" type="xsd:NMTOKEN" fixed="US"/>
 </xsd:complexType>

La conséquence de cette définition est que toute instance de cet élément dans l'instance (par exemple shipTo du fichier po.xml) doit être constituée de cinq éléments et d'un attribut. Ces éléments doivent être appelés name, street, city, state et zip conformément à ce qui est spécifié par les différentes valeurs de l'attribut name des déclarations de l'exemple ci-dessus. Ces cinq éléments doivent apparaître dans le même ordre que celui dans lequel ils sont déclarés dans le schéma. Les quatre premiers contiendront chacun une chaîne de caractères tandis que le cinquième contiendra un nombre. Les éléments qui auront USAddress comme type déclaré pourront recevoir un attribut appelé country qui devra alors avoir comme seul et unique contenu la chaîne de caractère US.

La définition de USAddress ne contient que des déclarations impliquant des types simples : string, decimal et NMTOKEN. Par opposition, la définition de PurchaseOrderType contient des déclarations d'éléments impliquant des types complexes, par exemple USAddress. Remarquez toutefois que dans les deux cas, c'est le même attribut type qui est utilisé pour identifier le type, que ce dernier soit simple ou complexe.

Définition du type PurchaseOrderType
 <xsd:complexType name="PurchaseOrderType">
  <xsd:sequence>
   <xsd:element name="shipTo" type="USAddress"/>
   <xsd:element name="billTo" type="USAddress"/>
   <xsd:element ref="comment" minOccurs="0"/>
   <xsd:element name="items"  type="Items"/>
  </xsd:sequence>
  <xsd:attribute name="orderDate" type="xsd:date"/>
 </xsd:complexType>

Dans la définition de PurchaseOrderType, les déclarations des deux éléments shipTo et billTo s'appuient sur le même type complexe USAddress. La conséquence de cette définition est que tout élément d'une instance de document (telle que po.xml) dont le type déclaré est PurchaseOrderType doit contenir les éléments shipTo et billTo,chacun contenant à leur tour les cinq sous-éléments (name, street, city, state et zip) déclarés dans la définition de USAddress. Les éléments shipTo et billTo peuvent également recevoir l'attribut country qui fait partie de la définition de USAddress.

La définition de PurchaseOrderType contient la déclaration de l'attribut orderDate qui, comme ce fut le cas pour l'attribut country, utilise un type simple. En fait, toutes les déclarations d'attributs ne peuvent que référencer des types simples car, contrairement aux éléments, les attributs ne peuvent pas contenir eux-mêmes d'autres attributs ou éléments.

Les déclarations d'éléments dont nous avons parlé jusque ici sont toutes composées d'une association entre un nom et une définition de type existante. Quelquefois il est préférable d'utiliser un élément existant plutôt que d'en déclarer un nouveau, par exemple:

<xsd:element ref="comment" minOccurs="0"/>

Cette déclaration utilise un élément déjà défini par ailleurs dans le schéma des bons de commande dont le nom est comment. En général, la valeur de l'attribut ref doit être celle d'un élément global, c'est à dire un élément déclaré directement à l'intérieur de schema et non à l'intérieur d'une définition de type complexe. La conséquence est qu'un élément appelé comment peut être présent dans une instance de document et que son contenu doit être conforme à ce type d'élément, à savoir string.

2.2.1 Contraintes d'occurrence

Dans PurchaseOrderType, l'élément comment est défini comme étant optionnel par le biais de la valeur 0 de l'attribut minOccurs. En général, un élément est requis quand la valeur de minOccurs vaut 1 ou plus. Le nombre maximum de fois qu'un élément peut apparaître est déterminé dans sa déclaration par la valeur de l'attribut maxOccurs. Cette valeur peut être un entier positif comme par exemple 41, ou encore le mot unbounded qui signifie qu'il n'y a pas de valeur limite. La valeur par défaut dans les deux cas (minOccurs et maxOccurs) est 1. Par conséquent, quand l'élément comment est déclaré sans que l'attribut maxOccurs soit précisé, cela signifie qu'il ne peut pas apparaître plus d'une fois. Soyez certains que lorsque vous ne précisez que la valeur de l'attribut minOccurs, celle-là soit inférieur ou au plus égale à la valeur par défaut de maxOccurs, c'est à dire 0 ou 1. A contrario, si vous ne faites que spécifier une valeur pour le seul attribut maxOccurs, vous devez être certain que cette valeur soit supérieure ou au moins égale à la valeur par défaut de minOccurs, c'est à dire 1 ou plus. Si les deux attributs sont omis, l'élément doit apparaître exactement une seule fois.

Les attributs peuvent apparaître au maximum une fois et donc la syntaxe pour spécifier le nombre d'occurrences autorisées d'un attribut est différente de celle utilisée pour les éléments. En particulier, les attributs peuvent être déclarés avec l'attribut de spécification use qui permet d'en préciser la contrainte d'apparition, les valeurs possibles sont required (regardez par exemple la déclaration de l'attribut partNum dans po.xsd), optional, ou même prohibited.

Les valeurs par défaut des attributs comme des éléments sont déclarées en utilisant l'attribut default, bien que cette attribut ait des conséquences sensiblement différentes dans chaque cas de figure. Quand une valeur est déclarée par défaut pour un attribut en particulier, alors cela signifie que la valeur de l'attribut sera librement précisée dans l'instance ou, si aucune valeur n'est clairement précisée dans l'instance, alors le programme de traitement doit considérer que sa valeur est celle déclarée par défaut dans le schéma. Notez que les valeurs par défaut des attributs n'ont de sens que si les attributs eux-mêmes sont optionnels, c'est donc une erreur que de spécifier simultanément une valeur par défaut et une contrainte d'apparition autre que optional dans use.

Le programme de traitement du schéma traite les contenus d'éléments par défaut de manière sensiblement différente que pour les attributs. Quand un élément est déclaré comme ayant un contenu par défaut, le contenu de l'élément dans une instance de document sera celui qui s'y trouve mais si le contenu de l'élément dans l'instance n'est pas précisé, alors le programme de traitement du schéma devra considérer que le contenu par défaut s'applique, il sera alors constitué de l'élément dont le nom est égal à la valeur de l'attribut default. Toutefois, si l'élément n'apparaît pas du tout dans une instance de document, alors le programme de traitement du schéma ne doit pas chercher à intégrer son contenu par défaut. En résumé, les différences entre les valeurs par défaut des attributs et des éléments peuvent être ramenées à : les valeurs par défaut des attributs s'appliquent quand l'attribut est omis alors que les valeurs par défaut des éléments s'appliquent quand l'élément est vide.

L'attribut fixed est utilisé à la fois dans les déclarations d'éléments et les déclarations d'attributs pour s'assurer que que leurs valeurs soient mises à une valeur prédéfinie. Par exemple, po.xsd contient la déclaration de l'attribut country, déclaré avec une valeur de type fixed égale à US. Cette déclaration signifie que l'utilisation de l'attribut country dans une instance de document est optionnelle (la valeur par défaut de use est optional), mais, si cet attribut apparaît, alors sa valeur doit être US et, si l'attribut n'apparaît pas, alors le processeur devra considérer que l'attribut country est présent par défaut et que sa valeur est US. Remarquez que les concepts de valeur fixe et de valeur par défaut s'excluent mutuellement, c'est donc une erreur que d'utiliser les valeurs fixed et default dans la même déclaration d'attribut.

Les valeurs des attributs utilisées dans les déclarations d'éléments et d'attributs pour contraindre leurs règles d'utilisation dans les instances sont résumées dans le Tableau 1.

Tableau 1. Contraintes d'occurrence des éléments et des attributs
Eléments
(minOccurs, maxOccurs) fixed, default 
Attributs
use, fixed, default
Remarques
(1, 1) -, - required, -, - l'élément ou l'attribut doit apparaître une seule fois, il peut prendre n'importe quelle valeur
(1, 1) 37, - required, 37, - l'élément ou l'attribut doit apparaître une seule fois, sa valeur doit être 37
(2, unbounded) 37, - non applicable l'élément doit apparaître deux fois ou plus, sa valeur doit être 37; en général, les valeurs de minOccurs et maxOccurs sont des entiers positifs, mais maxOccurs peut également prendre la valeur "unbounded"
(0, 1) -, - optional, -, - l'élément ou l'attribut peut apparaître 0 ou une fois et peut prendre n'importe quelle valeur
(0, 1) 37, - optional, 37, - l'élément ou l'attribut peut apparaître 0 ou une fois; quand il apparaît, sa valeur doit être égale à 37; si l'attribut est omis, sa valeur est fixée à 37. Si l'élément est omis, le processeur ne lui impose pas une valeur particulière.
(0, 1) -, 37 optional, -, 37 l'élément ou l'attribut peut apparaître 0 ou une fois; quand il apparaît, sa valeur est libre; si l'attribut est omis, sa valeur par défaut est 37. Si l'élément est omis, sa valeur n'est pas imposée ; si l'élément est vide, sa valeur est alors 37.
(0, 2) -, 37 non applicable l'élément ou l'attribut peut apparaître 0, une ou deux fois; il n'y un pas de possibilité équivalente pour les attributs. la valeur du contenu de l'élément n'est pas fixée mais si l'élément est vide la valeur considérée par le processeur sera, par défaut, 37;
(0, 0) -, - prohibited, -, - l'élément ou l'attribut ne doit pas apparaître
Notez que ni minOccurs, maxOccurs, ni use ne peuvent apparaître dans les déclarations globales d'éléments ou d'attributs.

2.2.2 Les attributs et éléments globaux

Les éléments et les attributs globaux sont créés par des déclarations qui apparaissent directement à l'intérieur de l'élément schema. Une fois déclaré, un élément ou un attribut global peut être référencé dans une ou plusieurs déclarations en utilisant l'attribut ref, comme cela a déjà été vu plus haut. Une déclaration qui référence un élément global permet à l'élément référencé d'être utilisé dans une instance de document dans le contexte de la déclaration qui le référence. Aussi, par exemple, l'élément comment apparaît dans po.xml au même niveau que les éléments shipTo, billTo et items parce que la déclaration qui référence comment se trouve dans une définition de type complexe au même niveau que que les déclarations des trois autres éléments.

La déclaration d'un élément global permet aussi à l'élément d'être utilisé au plus haut niveau d'une instance de document, c'est à dire comme élément racine. Ainsi purchaseOrder, qui est déclaré comme élément global dans po.xsd, peut apparaître comme élément racine de po.xml. Remarquez que ce même raisonnement permettrait également à l'élément comment d'être utilisé à la racine de po.xml.

Il y a un certain nombre de pièges concernant l'utilisation des éléments et des attributs globaux. L'un d'eux est que les déclarations globales ne peuvent pas contenir de référence ; les déclarations globales doivent identifier des types simples ou complexes directement. Pour parler concrètement, les déclarations globales ne peuvent pas utiliser l'attribut ref, elles doivent uniquement utiliser l'attribut type (ou, comme nous le décrivons brièvement, être suivies d'une définition de type anonymous). Un deuxième piège est que les contraintes de cardinalité ne peuvent pas être posées sur des déclarations globales alors qu'elles peuvent être utilisées sur des déclarations locales référençant des déclarations globales. En d'autres termes, les déclarations globales ne peuvent pas faire appel aux attributs minOccurs, maxOccurs, ou use.

2.2.3 Conflits de nommage

Nous avons maintenant décrit la manière de définir de nouveaux types complexes (par exemple PurchaseOrderType), déclarer des éléments (par exemple purchaseOrder) et des attributs (par exemple orderDate). Ces actions, en général, impliquent de choisir des noms, et la question vient ainsi naturellement à être posée : qu'arrive-t-il si deux objets portent le même nom ? La réponse dépend de la nature des deux objets en question, en règle général évidemment, plus les deux objets seront similaires et plus leurs noms seront conflictuels.

Voici quelques exemples pour illustrer les cas où les noms posent problème. Si les deux objets sont du même type, par exemple, supposons qu'on ait défini un type complexe baptisé USStates et un type simple du même nom, il y a de facto un conflit. Si les deux objets sont de nature différente, par exemple un élément et un type, disons par exemple qu'on ait défini un type complexe appelé USAddress et un élément du même nom, il n'y aura pas de conflit. Si les deux objets sont déclarés à l'intérieur de types différents (c'est à dire qu'il ne s'agit pas d'éléments globaux), par exemple un élément appelé name à l'intérieur du type USAddress et un autre de même nom à l'intérieur du type Item, il n'y a pas de conflit de nom (ces déclarations sont parfois appelées déclarations d'éléments locaux). Finalement, si les deux objets sont des types dont l'un est défini par vous même et l'autre provienne de XML Schema, par exemple un type simple appelé decimal défini par vous même, il n'y a pas de conflit. La raison de l'apparente contradiction du dernier exemple est que les deux types appartiennent à des espaces de noms différents. Nous explorerons l'utilisation des espaces de noms dans les schémas dans l'un des chapitres qui suivent.

2.3 Types simples

Le schéma de notre bon de commande fait appel à plusieurs éléments et attributs de types simples. Quelques uns de ces types simples, tels que string et decimal, sont prédéfinis dans XML Schema tandis que d'autres sont dérivés de ces types pré-éxistants. Par exemple, l'attribut partNum a un type appelé SKU (comme "Stock Keeping Unit") dérivé de string. Les types simples prédéfinis, tout comme leurs dérivées, peuvent être utilisés dans toute déclaration d'éléments ou d'attributs. Le Tableau 2 liste tous les types simples prédéfinis de XML Schema, en association avec des exemples d'utilisation des différents types.

Tableau 2. Types simples prédéfinis de XML Schema
Type simple exemples (délimités par des virgules) Remarques
string Confirmez que ceci est électrique  
normalizedString Confirmez que ceci est électrique cf (3)
token Confirmez que ceci est électrique cf (4)
byte -1, 126 cf (2)
unsignedByte 0, 126 cf (2) 
base64Binary GpM7  
hexBinary 0FB7  
integer -126789, -1, 0, 1, 126789 cf (2)
positiveInteger 1, 126789 cf (2)
negativeInteger -126789, -1 cf (2)
nonNegativeInteger 0, 1, 126789 cf (2)
nonPositiveInteger -126789, -1, 0 cf (2)
int -1, 126789675 cf (2)
unsignedInt 0, 1267896754 cf (2)
long -1, 12678967543233 cf (2)
unsignedLong 0, 12678967543233 cf (2)
short -1, 12678 cf (2)
unsignedShort 0, 12678 cf (2)
decimal -1.23, 0, 123.4, 1000.00 cf (2)
float -INF, -1E4, -0, 0, 12.78E-2, 12, INF, NaN équivalent aux nombres flottants simple-précision sur 32-bit, NaN signifie "not un nombre", cf (2)
double -INF, -1E4, -0, 0, 12.78E-2, 12, INF, NaN équivalent aux nombres flottants double-précision sur 64-bit, cf (2)
boolean true, false
1, 0
 
time 13:20:00.000, 13:20:00.000-05:00 cf (2)
dateTime 1999-05-31T13:20:00.000-05:00 31 mai 1999 à 13h20 heure standard de l'Est qui a 5 heures de décalage avec le temps universel, cf (2)
duration P1Y2M3DT10H30M12.3S 1 an, 2 mois, 3 jours, 10 heures, 30 minutes, et 12.3 secondes
date 1999-05-31 cf (2)
gMonth --05-- Mai, cf (2) (5)
gYear 1999 1999, cf (2) (5)
gYearMonth 1999-02 le mois de février 1999, indépendamment du nombre de jours, cf (2) (5)
gDay ---31 le 31ième jour, cf (2) (5)
gMonthDay --05-31 chaque 31 mai, cf (2) (5)
Name shipTo Type nom de XML 1.0
QName po:USAddress Nom XML qualifié par un espace de nom
NCName USAddress Nom XML non qualifié ni par un espace de nom ni par le deux points.
anyURI http://www.example.com/, http://www.example.com/doc.html#ID5  
language en-GB, en-US, fr valeurs valides de xml:lang telles que définies dans XML 1.0
ID   attribut de type ID tel que défini par XML 1.0, cf (1)
IDREF   attribut de type IDREF tel que défini par XML 1.0, cf (1)
IDREFS   attribut de type IDREFS tel que défini par XML 1.0, cf (1)
ENTITY   attribut de type ENTITY tel que défini par XML 1.0, cf (1)
ENTITIES   attribut de type ENTITIES tel que défini par XML 1.0, cf (1)
NOTATION   attribut de type NOTATION tel que défini par XML 1.0, cf (1)
NMTOKEN US,
Brésil
attribut de type NMTOKEN tel que défini par XML 1.0, cf (1)
NMTOKENS US UK,
Brésil Canada Mexique
attribut de type NMTOKENS tel que défini par XML 1.0, il s'agit d'une suite de NMTOKEN séparés les uns des autres par un espace blanc, cf (1)
Remarques: (1) Pour conserver la compatibilité entre XML Schema et les DTD de la version 1.0 de XML, les types simples ID, IDREF, IDREFS, ENTITY, ENTITIES, NOTATION, NMTOKEN, NMTOKENS ne doivent être utilisés que pour des attributs. (2) Une valeur de ce type peut être représentée par plus d'une forme lexicale, par exemple 100 et 1.0E2 sont deux formats valides de représentation flottante du nombre cent. Toutefois, des règles ont été établies pour ce type qui défini une forme lexicale canonique, cf XML Schema Part 2. (3) Les caractères retour chariot, tabulation et changement de ligne du type normalizedString sont convertis en caractères de type espace avant le traitement du schéma. (4) Comme pour normalizedString, les séquences de caractères adjacents de type espace sont ramenés à un seul caractère espace, et les blancs de tête et de queue sont retirés. (5) Le préfixe "g" signale une référence temporelle au calendrier Grégorien.

Les nouveaux types simples sont définis par dérivation des types simples déjà existants (ceux qui sont prédéfinis comme ceux qui sont dérivés). En particulier, on peut dériver un nouveau type simple en réduisant un type simple existant, en d'autres termes, la fourchette des valeurs autorisées du nouveau type est un sous-ensemble du type original. Nous utilisons l'élément de type simpleType pour définir et nommer le nouveau type simple. Nous utilisons l'élément restriction pour indiquer quel est le type original (appelé type de base) et pour identifier les "facettes" qui restreignent la fourchette de valeurs. Une liste complète des facettes est fournie en Annexe B.

Supposez que nous souhaitions créer un nouveau type d'entier appelé myInteger dont la fourchette des valeurs autorisées est comprise entre 10000 et 99999 (inclus). Nous basons notre définition sur le type simple prédéfini integer, dont la fourchette de valeurs autorisées comprend, bien sûr, des valeurs inférieures à 10000 et supérieures à 99999. Pour définir myInteger, on restreint la fourchette des valeurs du type de base integer en appliquant deux facettes appelées minInclusive et maxInclusive :

Définition de myInteger dont les valeurs autorisées sont comprises entre 10000 et 99999
<xsd:simpleType name="myInteger">
  <xsd:restriction base="xsd:integer">
    <xsd:minInclusive value="10000"/>
    <xsd:maxInclusive value="99999"/>
  </xsd:restriction>
</xsd:simpleType>

L'exemple montre une combinaison particulière de l'utilisation d'un type de base et de deux facettes pour définir myInteger, mais un simple regard à la liste des types simples prédéfinis et de leurs facettes associées de l'annexe B montre d'autres possibilités de combinaisons pour un résultat identique.

Le schéma des bons de commande contient un autre exemple, plus sophistiqué, de définition de type simple. Un nouveau type simple appelé SKU est dérivé (par restriction) du type simple string. De plus, nous contraignons les valeurs de SKU en utilisant une facette appelée pattern combinée à l'application de l'expression régulière "\d{3}-[A-Z]{2}" ce qui se lit "trois chiffres suivis d'un trait d'union suivi de deux lettres majuscules comprises entre A et Z":

Définition du type simple SKU
<xsd:simpleType name="SKU">
  <xsd:restriction base="xsd:string">
    <xsd:pattern value="\d{3}-[A-Z]{2}"/>
  </xsd:restriction>
</xsd:simpleType>

Le langage des expressions régulières est décrit plus complètement en Annexe D.

XML Schema définit quinze facettes qui sont listées en Annexe B. Parmis celles-là, la facette enumeration est particulièrement utile et permet d'exprimer des contraintes pour pratiquement tous les types simples, à l'exception du type boolean. La facette enumeration limite un type simple à un ensemble de valeurs distinctes. Par exemple, nous pouvons utiliser la facette enumeration pour définir un nouveau type simple appelé USState, dérivé de string, dont la valeur telle que définie doit être l'une des abréviations officielles des états américains :

Utilisation de la facette enumeration :
<xsd:simpleType name="USState">
  <xsd:restriction base="xsd:string">
    <xsd:enumeration value="AK"/>
    <xsd:enumeration value="AL"/>
    <xsd:enumeration value="AR"/>
    <!-- et so on ... -->
  </xsd:restriction>
</xsd:simpleType>

USState est un bon candidat pour le remplacement du type string utilisé dans la déclaration de l'élément state. En faisant cette substitution, les valeurs légales de l'élément state, plus précisément les sous-éléments state de billTo et shipTo, seront limitées à l'une des valeurs AK, AL, AR, etc. Remarquez que les valeurs de l'énumération, spécifiées pour un certain type en particulier, doivent être uniques.

2.3.1 Types de listes

XML Schema offre les notions de typage de listes, en plus des si bien nommés types atomiques qui sont à la base de la plupart des cas de typage présentés dans le tableau 2. (les types atomique, liste et union décrits dans le chapitre suivant sont collectivement appelés des types simples). La valeur d'un type atomique est indivisible du point de vue de XML Schema. Par exemple, la valeur NMTOKEN US est indivisible dans ce sens qu'aucune partie de US, comme par exemple le caractère "S", n'a de sens intrinsèque propre. Par opposition, les types liste sont des séries de types atomique ce qui fait que chaque élément d'une telle séquence (les "atomes") est lui-même significatif du point de vue de son typage. Par exemple, NMTOKENS est un type liste constitué d'une série d'éléments de type NMTOKEN délimités par un espace blanc faisant office de séparateur, comme par exemple la suite "US UK FR". XML Schema a trois types de listes prédéfinis, il s'agit des types NMTOKENS, IDREFS et ENTITIES.

Pour compléter l'utilisation des types prédéfinis de listes, il est possible de créer de nouveaux types de listes par dérivation des types atomiques existant. (Vous ne pouvez créer de nouveaux types de listes ni à partir des types listes existant, ni à partir des types complexes).

Exemple, création d'une liste de myInteger
<xsd:simpleType name="listOfMyIntType">
  <xsd:list itemType="myInteger"/>
</xsd:simpleType>

Ce qui pourra donner lieu dans une instance de document à l'exemple suivant :

<listOfMyInt>20003 15037 95977 95945</listOfMyInt>

Plusieurs facettes peuvent être appliquées au type liste : length, minLength, maxLength, et enumeration. Par exemple, pour définir une liste d'exactement six états US (SixUSStates), nous commençons par définir un nouveau type liste appelé USStateList à partir du type USState que nous dérivons ensuite en SixUSStates par restriction de USStateList à seulement six items :

Exemple de définition d'un type liste composé de six états américains
<xsd:simpleType name="USStateList">
 <xsd:list itemType="USState"/>
</xsd:simpleType>

<xsd:simpleType name="SixUSStates">
 <xsd:restriction base="USStateList">
  <xsd:length value="6"/>
 </xsd:restriction>
</xsd:simpleType>

Les éléments dont le type est SixUSStates doivent avoir six items et chacun d'eux doit prendre l'une des valeurs atomiques du type énuméré USState, par exemple :

<sixStates>PA NY CA NY LA AK</sixStates>

Remarquez qu'il est possible de dériver un type liste à partir du type atomique string. Toutefois, un type string peut contenir des espaces blancs alors que ces mêmes espaces blancs servent à délimiter les items d'une liste, donc vous devez être prudents dans l'utilisation des types liste quand le type de base est string. Par exemple, supposons que nous ayons défini un type liste avec une facette length égale à 3 et un type de base string. La liste de trois items présentée ci-après est alors valide :

Asie Europe Afrique

Tandis que la liste de trois items présentée ci-après est illégale :

Asie Europe Amérique Latine

Même le terme "Amérique Latine" est légitime en tant que chaîne de caractères à l'extérieur de la liste, il provoque la création d'un quatrième item quand il est inclu dans la liste, l'espace blanc qu'il contient étant considéré comme séparateur. Cela rend le contenu de l'élément invalide par rapport à la contrainte définie dans son modèle (trois items maximum).

2.3.2 Types union

Les types atomique et liste permettent à un élément ou une valeur d'attribut d'être composés de une ou plusieurs instances d'un type atomique. Par contraste, un type union permet à un élément ou valeur d'attribut d'être composés d'une ou plusieurs instances d'un type résultant de l'union de plusieurs types atomique ou liste. Pour donner un exemple, nous allons créer un type union pour représenter les états américains par des bigrammes ou des listes de valeurs numériques. Le type union appelé dans notre exemple zipUnion est construit à partir d'un type atomique et d'un type liste :

Type union pour les Zipcodes
<xsd:simpleType name="zipUnion">
  <xsd:union memberTypes="USState listOfMyIntType"/>
</xsd:simpleType>

Quand nous définissons un type union, la valeur de l'attribut memberTypes est une liste de tous les types constituant l'union.

Maintenant, imaginez que nous ayons déclaré un élément appelé zips de type zipUnion, des instances valides de cet élément pourraient être :

<zips>CA</zips>
<zips>95630 95977 95945</zips>
<zips>AK</zips>

Deux facettes, pattern et enumeration, peuvent être appliquées à un type union.

2.4 Définitions du type anonyme

Les schémas peuvent être construits en définissant d'abord des ensembles de types nommés comme par exemple PurchaseOrderType puis en déclarant des éléments tels que purchaseOrder qui référencent les types en utilisant le constructeur type. Cette forme de construction de schéma est directe mais peut être non maniable, spécialement si vous définissez de nombreux types référencés seulement une fois et contenant très peu de contraintes. Dans ce cas, un type peut être plus efficacement défini sous la forme d'un type anonyme qui économise le travail de nommage explicite du type et de son référencement.

La définition du type Items dans po.xsd contient deux déclarations d'éléments qui utilisent des types anonymes (item et quantité). En général, vous pouvez identifier les types anonymes en notant l'absence de l'attribut type dans les déclarations d'éléments ou d'attributs, et par la présence d'une définition de type (simple ou complexe) sans nommage particulier :

Deux définitions de types anonymes
<xsd:complexType name="Items">
 <xsd:sequence>
  <xsd:element name="item" minOccurs="0" maxOccurs="unbounded">
   <xsd:complexType>
    <xsd:sequence>
     <xsd:element name="productName" type="xsd:string"/>
     <xsd:element name="quantity">
      <xsd:simpleType>
       <xsd:restriction base="xsd:positiveInteger">
        <xsd:maxExclusive value="100"/>
       </xsd:restriction>
      </xsd:simpleType>
     </xsd:element>
     <xsd:element name="USPrice"  type="xsd:decimal"/>
     <xsd:element ref="comment"   minOccurs="0"/>
     <xsd:element name="shipDate" type="xsd:date" minOccurs="0"/>
    </xsd:sequence>
    <xsd:attribute name="partNum" type="SKU" use="required"/>
   </xsd:complexType>
  </xsd:element>
 </xsd:sequence>
</xsd:complexType>

L'élément item a un type anonyme complexe constitué des éléments productName, quantité, USPrice, comment et shipDate et d'un attribut appelé partNum. L'élément quantity a un type anonyme simple dérivé du type integer dont la fourchette de valeurs est comprise entre 1 et 99.

2.5 Contenu d'un élément

Le schéma du bon de commande montre plusieurs cas de contenus : des éléments sans attribut dont le contenu est constitué de sous-éléments (par exemple items), des éléments avec attributs et un contenu formé de sous-éléments (par exemple shipTo) et enfin des éléments contenant seulement un type simple de valeurs (par exemple USPrice). Toutefois, nous n'avons vu ni élément ayant des attributs mais ne contenant qu'un type simple de valeurs, ni élément ayant un contenu mixte (c'est à dire pouvant contenir à la fois des caractères de données mélangés à des sous-éléments), ni élément vide (n'ayant aucun contenu du tout). Dans ce chapitre, nous allons examiner ces cas particuliers de modèles de contenu.

2.5.1 Types complexes dérivés de types simples

Tout d'abord, considérons la manière de déclarer un élément ayant un attribut et contenant une valeur simple. Dans une instance, un tel élément pourrait être écrit par exemple :

<internationalPrice currency="EUR">423.46</internationalPrice>

Pour la suite de notre explication, nous allons utiliser le cas de l'élément USPrice, déclaré comme suit dans le schéma du bon de commande :

<xsd:element name="USPrice" type="decimal"/>

Comment ajouter un attribut à cet élément ? Il est de type simple decimal et, comme nous l'avons dit plus haut, ces types ne peuvent avoir d'attribut. A partir de là, nous devons définir un type complexe pour incorporer la déclaration de l'attribut. Nous voulons aussi que le contenu de l'attribut soit de type decimal. Donc, notre question originale devient : Comment définit-on un type complexe basé sur le type simple decimal? La réponse est obtenue en dérivant un nouveau type complexe à partir du type simple decimal comme ceci :

 <xsd:element name="internationalPrice">
  <xsd:complexType>
   <xsd:simpleContent>
    <xsd:extension base="xsd:decimal">
     <xsd:attribute name="currency" type="xsd:string"/>
    </xsd:extension>
   </xsd:simpleContent>
  </xsd:complexType>
 </xsd:element>

Nous utilisons l'élément complexType pour commencer la définition du nouveau type (en l'occurrence, il s'agit d'un type anonyme). Pour indiquer que le modèle de contenu du nouveau type ne contient que des caractères de données et aucun élément, on utilise l'élément facette simpleContent. Finalement, nous dérivons le nouveau type en étendant le type simple decimal. L'extension consiste à rajouter un attribut currency en utilisant une déclaration d'attribut standard (les dérivations de types sont détaillées au chapitre 4). L'élément internationalPrice déclaré de la sorte apparaîtra dans l'instance tel que montré au début de ce chapitre.

2.5.2 Contenu mixte

La construction du schéma des bons de commande peut être caractérisée comme étant basée sur des éléments imbriqués, les plus profonds d'entre eux (les feuilles) ne contenant que des données textuelles. XML Schema fournit aussi la possibilité de construire des schémas dans lesquels les caractères de données peuvent apparaître au même niveau que des sous-éléments, n'étant pas ainsi confinés au niveau des feuilles de l'arborescence : nous parlons alors de contenu mixte.

Pour illustrer ce propos, on considère l'extrait suivant, provenant d'une lettre d'un client dans laquelle il utilise quelques éléments issus du bon de commande :

<letterBody>
<salutation>Dear Mr.<name>Robert Smith</name>.</salutation>
Your order of <quantity>1</quantity> <productName>Baby
Monitor</productName> shipped from our warehouse on
<shipDate>1999-05-21</shipDate>. ....
</letterBody>

Remarquez que dans l'élément salutation, du texte est mélangé à des éléments enfants. Plus précisément, du texte apparaît entre les éléments salutation, quantity, productName et shipDate qui sont tous des enfants de l'élément letterBody. L'extrait suivant est la partie du schéma où est déclaré letterBody:

<xsd:element name="letterBody">
 <xsd:complexType mixed="true">
  <xsd:sequence>
   <xsd:element name="salutation">
    <xsd:complexType mixed="true">
     <xsd:sequence>
      <xsd:element name="name" type="xsd:string"/>
     </xsd:sequence>
    </xsd:complexType>
   </xsd:element>
   <xsd:element name="quantity"    type="xsd:positiveInteger"/>
   <xsd:element name="productName" type="xsd:string"/>
   <xsd:element name="shipDate"    type="xsd:date" minOccurs="0"/>
   <!-- etc. -->
  </xsd:sequence>
 </xsd:complexType>
</xsd:element>

Les éléments qui apparaissent dans la lettre du client sont déclarés et leurs types sont définis par des montages faits à partir des éléments element et complexType, comme nous l'avons déjà vu. Pour autoriser que des caractères de données puissent être mélangés aux éléments enfants de letterBody, l'attribut mixed est positionné à true dans la définition du type.

Remarquez que le modèle mixed de XML Schema est fondamentalement différent de celui précédemment défini dans XML 1.0. Avec ce nouveau modèle, l'ordre et le nombre des éléments enfants de l'instance doivent être en conformité avec ceux spécifiés dans le modèle. Alors que dans XML 1.0, ils ne pouvaient être imposés. En résumé, XML Schema fournit une validation complète des modèles de contenu mixte contrastant avec la validation seulement partielle de XML 1.0.

2.5.3 Contenu vide

Maintenant, supposons que nous voulions que l'élément internationalPrice ait une unité monétaire et un prix sous la forme d'un attribut au lieu que cela soit sous la forme d'un contenu :

<internationalPrice currency="EUR" value="423.46"/>

Un tel élément n'a pas de contenu du tout ; son modèle de contenu est vide. Pour définir un type dont le contenu est vide, le principe est de définir un type ne permettant d'avoir que des sous-éléments comme contenu, sous-éléments qui ne seront jamais déclarés.

<xsd:element name="internationalPrice">
 <xsd:complexType>
  <xsd:complexContent>
   <xsd:restriction base="xsd:anyType">
    <xsd:attribute name="currency" type="xsd:string"/>
    <xsd:attribute name="value"    type="xsd:decimal"/>
   </xsd:restriction>
  </xsd:complexContent>
 </xsd:complexType>
</xsd:element>

Dans cet exemple, nous définissons un type anonyme ayant un contenu de type complexContent, c'est à dire uniquement constitué d'éléments. L'élément complexContent indique que nous avons l'intention de restreindre ou d'étendre le modèle de contenu et la restriction à anyType permet de déclarer deux attributs mais n'introduit aucun sous-élément (cf Chapitre 4.4 pour plus de détails sur les restrictions). L'élément internationalPrice ainsi déclaré peut légitimement apparaître dans une instance sous la forme montrée dans l'exemple ci-dessus.

La syntaxe précédemment utilisée pour déclarer un élément vide est relativement verbeuse et il est possible de déclarer l'élément internationalPrice d'une manière plus compacte.

Raccourci pour déclarer un type complexe vide
<xsd:element name="internationalPrice">
 <xsd:complexType>
  <xsd:attribute name="currency" type="xsd:string"/>
  <xsd:attribute name="value"    type="xsd:decimal"/>
 </xsd:complexType>
</xsd:element>

Cette syntaxe compacte marche parce que la définition d'un type complexe sans utilisation aucune de simpleContent ou complexContent est interprétée comme étant un raccourci pour définir un contenu complexe réduit à anyType.

2.5.4 Contenu libre

Le mot anyType représente une abstraction appelée ur-type qui est le type de base à partir duquel tous les types simples et complexes sont dérivés. Un type anyType ne contraint un contenu d'aucune manière. Il est possible d'utiliser anyType comme n'importe quel autre type, par exemple :

<xsd:element name="anything" type="xsd:anyType"/>

Le contenu de l'élément déclaré de cette manière n'est pas contraint, la valeur de l'élément peut donc être 423.46 comme n'importe quelle autre séquence de caractères, ou un mélange de caractères et de sous-éléments. En fait, anyType est le type par défaut quand aucun type n'est spécifié, aussi, l'exemple précédent pourrait s'écrire comme suit :

<xsd:element name="anything"/>

Si un contenu d'élément libre est nécessaire, par exemple dans le cas où il est nécessaire d'embarquer du balisage étranger dans un élément, alors la déclaration par défaut ou une forme légèrement restreinte peut être pratique. Le type text décrit au Chapitre 5.5 est un exemple d'un tel type.

2.6 Annotations

XML Schema fournit trois éléments dont l'objectif est de commenter les schémas de manière à ce que les commentaires puissent être lus aussi bien par des humains que par des applications. Dans le cas du schéma des bons de commande, nous mettons une description sommaire du schéma ainsi qu'une information de copyright à l'intérieur de l'élément documentation, ce qui est l'endroit recommandé pour les commentaires à destination des lecteurs. Nous recommandons d'utiliser l'attribut xml:lang avec tout élément documentation pour en préciser la langue d'écriture. Une autre manière de faire consiste à placer cet attribut sur l'élément de plus haut niveau, schema, pour indiquer que la langue précisée s'applique à tous les commentaires présents dans le schéma.

L'élément appInfo, que nous n'avons pas utilisé dans le schéma des bons de commande, peut être utilisé pour transmettre de l'information aux outils, feuilles de styles et autres applications qui en auraient besoin. Un exemple intéressant utilisant appInfo est le schéma décrivant les types simples de XML Schema (cf le tome 2). Les informations de description de ce schéma, faites à l'intérieur d'éléments appInfo, présentent les facettes applicables à des types simples en particulier, ont été reprises automatiquement par un programme pour produire le texte du tome 2 de XML Schema.

Les deux éléments documentation et appInfo apparaissent comme des sous-éléments de annotation, qui pourrait lui-même apparaître au début de bien des schémas. Pour illustrer ce propos, l'exemple suivant montre l'utilisation d'éléments annotation au début d'une déclaration d'élément et d'une définition d'un type complexe :

<xsd:element name="internationalPrice">
 <xsd:annotation>
  <xsd:documentation xml:lang="en">
      élément déclaré with anonymous type
  </xsd:documentation>
 </xsd:annotation>
 <xsd:complexType>
  <xsd:annotation>
   <xsd:documentation xml:lang="en">
       empty anonymous type with 2 attributs
   </xsd:documentation>
  </xsd:annotation>
  <xsd:complexContent>
   <xsd:restriction base="xsd:anyType">
    <xsd:attribute name="currency" type="xsd:string"/>
    <xsd:attribute name="value"    type="xsd:decimal"/>
   </xsd:restriction>
  </xsd:complexContent>
 </xsd:complexType>
</xsd:element>

L'élément annotation peut aussi apparaître au début d'autres structures de schémas telles que celles des éléments schema, simpleType, et attribute.

2.7 Construction de modèles de contenu

Dans le schéma des bons de commande, les types complexes sont tous définis avec des séquences d'éléments devant apparaître dans les instances. Les occurrences des éléments individuellement déclarés dans ces modèles peuvent être optionnelles, comme cela est le cas quand l'attribut minOccurs vaut 0 (par exemple dans comment) ou être contrainte de diverses manières en fonction des valeurs de minOccurs et maxOccurs. XML Schema permet aussi d'exprimer des contraintes s'appliquant aux groupes d'éléments des modèles de contenu. Ces contraintes reflètent celles disponibles avec XML 1.0 et les complètent par quelques restrictions supplémentaires. Remarquez que les contraintes ne s'appliquent pas aux attributs.

XML Schema permet de créer et de nommer des groupes d'éléments afin que les éléments puissent être utilisés pour construire les modèles de contenu de type complexe (singeant ainsi le mécanisme des entités paramètres de XML 1.0). Des groupes anonymes d'éléments peuvent également être définis qui, comme les éléments des groupes nommés, peuvent être contraints d'apparaître dans le même ordre (séquence) que leur ordre de déclaration. D'un autre côté, ils peuvent être contraints de manière à ne laisser qu'un seul de ces éléments apparaître dans une instance.

Pour donner un exemple, nous introduisons deux groupes dans la définition du type PurchaseOrderType du schéma des bons de commande de telle manière que les bons de commande puissent contenir au choix une ou deux adresses distinctes de facturation et de livraison :

Exemple de groupes de type choix et séquence imbriqués :
<xsd:complexType name="PurchaseOrderType">
 <xsd:sequence>
  <xsd:choice>
   <xsd:group   ref="shipAndBill"/>
   <xsd:element name="singleUSAddress" type="USAddress"/>
  </xsd:choice>
  <xsd:element ref="comment" minOccurs="0"/>
  <xsd:element name="items"  type="Items"/>
 </xsd:sequence>
 <xsd:attribute name="orderDate" type="xsd:date"/>
</xsd:complexType>

<xsd:group name="shipAndBill">
  <xsd:sequence>
    <xsd:element name="shipTo" type="USAddress"/>
    <xsd:element name="billTo" type="USAddress"/>
  </xsd:sequence>
</xsd:group>

Le groupe choice signifie qu'un seul de ses éléments enfants pourra apparaître dans l'instance. Le premier des enfants est défini via l'élément group qui référence le groupe nommé shipAndBill, lui-même formé des éléments shipTo et billTo dans cet ordre et le deuxième élément du groupe est singleUSAddress. Il s'ensuit que dans une instance de document conforme à ce schéma, l'élément purchaseOrder contiendra soit une suite composée des éléments shipTo et billTo soit le seul élément singleUSAddress. Le groupe choice est ensuite suivi par les deux déclarations des éléments comment et items et tous sont des enfants de l'élément sequence. L'effet de ces différentes imbrications de groupes est que tout élément address doit être suivi des éléments comment et items dans cet ordre.

Une troisième type de contrainte de groupe : tous les éléments du groupe peuvent apparaître une fois mais dans n'importe quel ordre. L'usage du groupe all (version simplifiée du connecteur SGML &) est limité au plus haut niveau de tout modèle de contenu. Les enfants du groupe doivent tous être des éléments individuels (pas de sous-groupe) et aucun élément du modèle de contenu ne peut apparaître plus d'une fois, c'est à dire que les seules valeurs autorisées de minOccurs et maxOccurs sont 0 et 1. Par exemple, pour permettre aux éléments enfants de purchaseOrder d'apparaître dans n'importe quel ordre, nous pourrions redéfinir PurchaseOrderType comme ceci :

Un groupe de type all
<xsd:complexType name="PurchaseOrderType">
  <xsd:all>
    <xsd:element name="shipTo" type="USAddress"/>
    <xsd:element name="billTo" type="USAddress"/>
    <xsd:element ref="comment" minOccurs="0"/>
    <xsd:element name="items"  type="Items"/>
  </xsd:all>
  <xsd:attribute name="orderDate" type="xsd:date"/>
</xsd:complexType>

Par cette définition, un élément comment peut apparaître dans purchaseOrder (sans toutefois être obligatoire) avant ou après n'importe lequel des autres éléments shipTo, billTo et items du modèle de contenu. Il ne pourra de toute façon n'apparaître qu'une seule fois. De plus, il est stipule que dans le cas du groupe all nous ne pouvons déclarer un élément tel que comment en dehors du groupe comme moyen de contournement pour lui permettre d'apparaître plus d'une fois. XML Schema stipule en effet qu'un groupe all doit apparaître comme seul et unique enfant de premier niveau d'un modèle de contenu. En d'autres termes, la forme suivante est interdite parce que le groupe all qu'elle contient n'est pas le seul et unique enfant de premier niveau de la définition du type PurchaseOrderType :

Exemple d'utilisation prohibée du groupe All :
<xsd:complexType name="PurchaseOrderType">
 <xsd:sequence>
  <xsd:all>
    <xsd:element name="shipTo" type="USAddress"/>
    <xsd:element name="billTo" type="USAddress"/>
    <xsd:element name="items"  type="Items"/>
  </xsd:all>
  <xsd:sequence>
   <xsd:element ref="comment" minOccurs="0" maxOccurs="unbounded"/>
  </xsd:sequence>
 </xsd:sequence>
 <xsd:attribute name="orderDate" type="xsd:date"/>
</xsd:complexType>

Finalement, les groupes nommés ou non qui apparaissent dans les modèles de contenu (représenté respectivement par group, choice, sequence, all) peuvent être porteurs des attributs minOccurs et maxOccurs. En combinant et en entrelaçant les différents types de groupes fournis par XML Schema et en fixant les valeurs de minOccurs et maxOccurs, il est possible de représenter tous les modèles de contenu envisageables avec les DTD de XML 1.0. De plus, le groupe all fournit une puissance d'expression supérieure.

Remarque de la traduction française :

Il semblerait que, pour être encore plus explicite, l'exemple ci-dessus devrait être :

<xsd:complexType name="PurchaseOrderType">
 <xsd:sequence>
  <xsd:all>
    <xsd:element name="shipTo" type="USAddress"/>
    <xsd:element name="billTo" type="USAddress"/>
    <xsd:element ref="comment" minOccurs="0"/>
    <xsd:element name="items"  type="Items"/>
  </xsd:all>
  <xsd:sequence>
   <xsd:element ref="comment" minOccurs="0" maxOccurs="unbounded"/>
  </xsd:sequence>
 </xsd:sequence>
 <xsd:attribute name="orderDate" type="xsd:date"/>
</xsd:complexType>

Tel que l'exemple est écrit ci-dessus, la déclaration de l'élément comment apparaît à la fois dans le groupe all et à l'extérieur. C'est là que se trouve le véritable problème de cette formulation qui, dans son application dans les instances de documents, est la cause de formes ambiguës que les programmes de validation ne savent pas "désambigüifier". Par exemple, cette formulation autorise d'écrire dans une instance de document :

<PurchaseOrder>
<billTo>adresse de facturation</billTo>
<comment>commentaire</comment>
</PurchaseOrder>

Fragment dont un programme de validation ne saurait déterminer si la balise <comment> appartient au groupe all ou à la séquence suivante et par conséquent ne saurait valider ce fragment.

Fin de la remarque fait par la traduction française

2.8 Groupes d'attributs

Supposez que nous voulions fournir plus d'informations sur les articles qui composent le bon de commande, comme par exemple leur poids et la méthode d'expédition demandée. Nous pouvons obtenir ce résultat en ajoutant les déclarations de deux attributs weightKg et shipBy à la définition (de type anonyme) de l'élément item :

<xsd:element name="Item" minOccurs="0" maxOccurs="unbounded">
  <xsd:complexType>
   <xsd:sequence>
    <xsd:element   name="productName" type="xsd:string"/>
    <xsd:element   name="quantity">
     <xsd:simpleType>
      <xsd:restriction base="xsd:positiveInteger">
       <xsd:maxExclusive value="100"/>
      </xsd:restriction>
     </xsd:simpleType>
    </xsd:element>
    <xsd:element name="USPrice"  type="xsd:decimal"/>
    <xsd:element ref="comment"   minOccurs="0"/>
    <xsd:element name="shipDate" type="xsd:date" minOccurs="0"/>
   </xsd:sequence>
   <xsd:attribute name="partNum"  type="SKU" use="required"/>
   <!-- add weightKg and shipBy attributs -->
   <xsd:attribute name="weightKg" type="xsd:decimal"/>
   <xsd:attribute name="shipBy">
    <xsd:simpleType>
     <xsd:restriction base="xsd:string">
      <xsd:enumeration value="air"/>
      <xsd:enumeration value="land"/>
      <xsd:enumeration value="any"/>
     </xsd:restriction>
    </xsd:simpleType>
   </xsd:attribute>
  </xsd:complexType>
</xsd:element>

Une alternative serait de créer un groupe d'attributs nommé contenant tous les attributs souhaités de l'élément item puis de référencer ce groupe dans la déclaration de l'élément item :

Rajout d'attributs par utilisation d'un groupe d'attributs
<xsd:element name="item" minOccurs="0" maxOccurs="unbounded">
 <xsd:complexType>
  <xsd:sequence>
   <xsd:element name="productName" type="xsd:string"/>
   <xsd:element name="quantity">
    <xsd:simpleType>
     <xsd:restriction base="xsd:positiveInteger">
      <xsd:maxExclusive value="100"/>
     </xsd:restriction>
    </xsd:simpleType>
   </xsd:element>
   <xsd:element name="USPrice"  type="xsd:decimal"/>
   <xsd:element ref="comment"   minOccurs="0"/>
   <xsd:element name="shipDate" type="xsd:date" minOccurs="0"/>
  </xsd:sequence>

  <!-- attributeGroup replaces individual declarations -->
  <xsd:attributeGroup ref="ItemDelivery"/>
 </xsd:complexType>
</xsd:element>

<xsd:attributeGroup name="ItemDelivery">
  <xsd:attribute name="partNum"  type="SKU" use="required"/>
  <xsd:attribute name="weightKg" type="xsd:decimal"/>
  <xsd:attribute name="shipBy">
    <xsd:simpleType>
     <xsd:restriction base="xsd:string">
      <xsd:enumeration value="air"/>
      <xsd:enumeration value="land"/>
      <xsd:enumeration value="any"/>
     </xsd:restriction>
    </xsd:simpleType>
  </xsd:attribute>
</xsd:attributeGroup>

Cette utilisation d'un groupe d'attributs peut améliorer la lisibilité des schémas et faciliter leurs mises à jour parce qu'un groupe d'attributs peut être édité et modifié en une seule fois et être référencé dans de multiples définitions et déclarations. Cette caractéristique des groupes d'attributs est comparable à celle des entités paramètres de XML 1.0. Remarquez qu'un groupe d'attributs peut contenir d'autres groupes d'attributs. Remarquez aussi que les déclarations d'attributs tout comme les références à des groupes d'attributs doivent apparaître à la fin des définitions de types complexes.

Remarque faite par la traduction française :

La mutualisation des déclarations d'attributs et d'éléments au moyen des groupes d'attributs référencés a des limites et la remarque faite ci-dessus sur les facilités de mise à jour peut en réalité se retourner contre l'auteur du schéma lorsque celui-là aura trop usé de cette technique et des possibilités d'imbrication des groupes. Il faut donc faire preuve de discernement dans la mutualisation des définitions. A trop utiliser les groupes, le risque existe réellement d'avoir des schémas peu lisibles. La mise à jour s'avère alors complexe voir impossible (impossibilité de mesurer le réel impact d'une mise à jour sur l'ensemble des déclarations du schéma).

Fin de la remarque faite par la traduction française

2.9 Valeurs nil

L'un des items listés dans le bon de commande du fichier po.xml, le Lawnmower, n'a pas d'élément shipDate. Dans le contexte de notre scénario, l'auteur du schéma peut avoir eu l'intention d'autoriser cette absence pour indiquer les articles dont l'expédition n'a pas encore été effectuée. Mais en général, l'absence d'un élément n'a pas de signification particulière : cela peut signifier au choix que l'information est inconnue, ou qu'elle est non applicable, ou que l'élément est absent pour une quelconque autre raison. Parfois il est souhaitable de pouvoir représenter un article non expédié, une information inconnue ou inapplicable par un élément explicitement, plutôt que par l'absence d'un élément. Par exemple, il peut être souhaitable de représenter par la présence explicite d'un élément une valeur "nulle" échangée avec une base de données. De tels cas peuvent être résolus en utilisant le mécanisme nil de XML Schema qui permet à un élément d'apparaître avec ou sans une valeur non-nulle.

Pour cela, le mécanisme nil met en jeu un signal nil indirect. En d'autres termes, il n'y a pas de valeur nil apparaissant explicitement au niveau du modèle de contenu. Au lieu de cela, un attribut sert à indiquer que le contenu de l'élément est nul. Pour donner un exemple, nous modifions la déclaration de l'élément shipDate de telle manière que la valeur nil puisse être marquée :

<xsd:element name="shipDate" type="xsd:date" nillable="true"/>

Et pour explicitement représenter que shipDate a une valeur nil dans une instance de document, il suffit de mettre la valeur de l'attribut nil à true :

<shipDate xsi:nil="true"></shipDate>

L'attribut nil provient de l'espace des noms de XML Schema applicables aux instances http://www.w3.org/2001/XMLSchema-instance, en conséquence de quoi il doit être préfixé dans une instance de document du préfixe (tel que xsi:) associé à cet espace de noms (comme pour le préfixe xsd:, le préfixe xsi: est utilisé seulement par convention). Remarquez que le mécanisme nil ne s'applique qu'aux contenus d'éléments et pas à la valeur de leurs attributs. Un élément porteur de la valeur xsi:nil="true" n'a aucun contenu mais peut porter d'autres attributs.

3. Concepts avancés I : espaces de noms, schémas et qualification

Un schéma peut être vu comme une collection (un vocabulaire) de définitions de types et déclarations d'éléments dont les noms appartiennent à un espace de noms particulier appelé espace de noms cible. lls nous permettent de distinguer les définitions et les déclarations appartenant à des vocabulaires différents. Par exemple, cela nous permet de faire la distinction entre la déclaration element du vocabulaire de XML Schema et celle du même mot element d'un vocabulaire qui serait spécifique à une application XML dans le domaine de la chimie. Le premier des deux mots fait partie de l'espace de noms cible http://www.w3.org/2001/XMLSchema et le deuxième ferait partie d'un autre espace de noms cible.

Quand nous voulons vérifier qu'une instance de document est conforme à un ou plusieurs schémas (au moyen d'un traitement appelé validation de schéma), le programme doit être capable de faire la différence entre les déclarations d'éléments et d'attributs et les définitions de types des différents schémas. L'espace de noms cible joue un rôle important dans le processus d'identification. Nous examinons le rôle de l'espace de noms cible au chapitre suivant.

L'auteur du schéma a aussi plusieurs options à sa disposition pour modifier la manière dont l'identité des éléments et des attributs est représentée dans les instances de documents. Plus précisément, l'auteur peut décider si l'écriture des éléments et des attributs déclarés localement doit être qualifiée par un espace de noms, soit via un préfixe explicite soit une valeur implicite par défaut. Le choix de l'auteur du schéma vis à vis de la qualification des éléments et des attributs locaux a un certain nombre d'impacts sur les structures des schémas et des instances et nous en examinons quelques uns dans les chapitres qui suivent.

3.1 Espaces de noms cibles et noms locaux non qualifiés

Dans une version différente du schéma des bons de commande, po1.xsd, nous déclarons explicitement un espace de nom cible et nous spécifions que les éléments et les attributs définis localement ne doivent pas être qualifiés. L'espace de noms cible de po1.xsd est http://www.example.com/PO1, valeur indiquée par l'attribut targetNamespace.

La qualification d'éléments et d'attributs locaux peut être spécifiée soit globalement via la paire d'attributs elementFormDefault et attributeFormDefault de l'élément schema soit individuellement au niveau de chaque déclaration via l'attribut form. Ces attributs peuvent prendre soit la valeur unqualified soit la valeur qualified pour spécifier si les éléments et attributs qui les portent doivent être qualifiés.

Dans po1.xsd nous spécifions globalement la qualification des éléments et des attributs en initialisant les valeurs des deux attributs elementFormDefault et attributeFormDefault à unqualified. Stricto senso, ces initialisations ne sont pas nécessaires parce que les valeurs utilisées sont celles par défaut; nous les mettons en évidence uniquement pour bien souligner la différence avec d'autres cas que nous verrons plus loin.

Schéma des bons de commande avec un espace de nom cible et noms locaux non qualifiés, po1.xsd
<schema xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:po="http://www.example.com/PO1"
        targetNamespace="http://www.example.com/PO1"
        elementFormDefault="unqualified"
        attributeFormDefault="unqualified">

 <element name="purchaseOrder" type="po:PurchaseOrderType"/>
 <element name="comment"       type="string"/>

 <complexType name="PurchaseOrderType">
  <sequence>
   <element name="shipTo"    type="po:USAddress"/>
   <element name="billTo"    type="po:USAddress"/>
   <element ref="po:comment" minOccurs="0"/>
   <!-- etc. -->
  </sequence>
  <!-- etc. -->
 </complexType>

 <complexType name="USAddress">
  <sequence>
   <element name="name"   type="string"/>
   <element name="street" type="string"/>
   <!-- etc. -->
  </sequence>
 </complexType>

 <!-- etc. -->

</schema>

Pour voir comment l'espace de noms cible de ce schéma est peuplé, nous allons examiner tour à tour les définitions de types et les déclarations d'éléments, en commençant par la fin du schéma. En premier lieu, nous définissons le type appelé USAddress qui comprend les éléments name, street, etc. Faisant cela, le type USAddress est inclus dans l'espace de noms cible du schéma. Ensuite, nous définissons le type appelé PurchaseOrderType qui comprend les éléments shipTo, billTo, comment, etc. PurchaseOrderType est également inclus dans l'espace de nom cible du schéma. Remarquez que les références de type dans les trois déclarations d'éléments sont préfixées : po:USAddress, po:USAddress et po:comment ont le préfixe po:, associé à l'espace de noms http://www.example.com/PO1, le même que l'espace de noms cible du schéma. Ainsi, un programme de traitement du schéma saura regarder à l'intérieur du schéma pour y trouver la définition du type USAddress ainsi que la déclaration de l'élément comment. Il est également possible de référencer des types provenant d'autres schémas en utilisant des espaces de noms cibles différents, permettant ainsi la réutilisation de déclarations et de définitions.

Au début du schéma po1.xsd se trouvent les déclarations des éléments purchaseOrder et comment. Ils sont inclus dans l'espace de noms cible du schéma. Le type de l'élément purchaseOrder est préfixé pour la même raison qui fait que le type USAddress est préfixé. A contrario, le type string de l'élément comment n'est pas préfixé. Le schéma po1.xsd contient une déclaration d'espace de noms par défaut et par conséquent les types et les éléments sans préfixe tels que string, element et complexType sont associés à l'espace de noms par défaut http://www.w3.org/2001/XMLSchema. En fait, cela est l'espace de noms cible de XML Schema lui-même, faisant ainsi qu'un programme de traitement de po1.xsd saura regarder à l'intérieur du schéma de XML Schema -- encore connu comme étant "le schéma des schémas" -- pour y trouver la définition du type string ainsi que la déclaration de l'élément appelé element.

Regardons maintenant comment l'espace de noms cible du schéma a des effets sur une instance de document conforme :

Un bon de commande avec des noms locaux non qualifiés, po1.xml
<?xml version="1.0"?>
<apo:purchaseOrder xmlns:apo="http://www.example.com/PO1"
                   orderDate="1999-10-20">
    <shipTo country="US">
        <name>Alice Smith</name>
        <street>123 Maple Street</street>
        <!-- etc. -->
    </shipTo>
    <billTo country="US">
        <name>Robert Smith</name>
        <street>8 Oak Avenue</street>
        <!-- etc. -->
    </billTo>
    <apo:comment>Hurry, my lawn is going wild!</apo:comment>
    <!-- etc. -->
</apo:purchaseOrder>

Cette instance déclare un espace de nom, http://www.example.com/PO1, et l'associe au préfixe apo: utilisé pour qualifier deux éléments du document, à savoir purchaseOrder et comment. L'espace de noms est identique à celui défini comme cible dans le schéma po1.xsd et un programme de traitement de l'instance sait qu'il y trouvera leurs déclarations respectives. En fait, le mot cible a été choisi à cause du sens dans lequel il existe une relation entre les éléments purchaseOrder et comment et l'espace de noms référencé (note de la rédaction française : le programme de validation part du nom de l'élément et remonte jusqu'à l'espace de noms cible associé au préfixe de l'élément). Il s'ensuit que les espaces de noms cibles du schéma contrôlent la validation des espaces de noms correspondant de l'instance.

Le préfixe apo: est appliqué aux éléments globaux purchaseOrder et comment. En plus, les attributs elementFormDefault et attributeFormDefault imdiquent que le préfixe n'est pas obligatoire sur les attributs et les éléments locaux tels que shipTo, billTo, name et street. Les éléments purchaseOrder et comment sont globaux parce qu'ils ont été déclarés dans le schéma de manière générique plutôt que dans le cadre restrictif d'un type particulier. Par exemple, dans po1.xsd, la déclaration de purchaseOrder est un enfant direct de l'élément schema alors que celle de shipTo est un enfant de l'élément complexType utilisé pour définir l'élément PurchaseOrderType.

Quand la qualification des éléments et des attributs locaux n'est pas requise, l'auteur d'une instance pourra avoir besoin de plus ou moins de connaissance sur le schéma pour écrire des documents valides. Plus précisément, si l'auteur peut être certain que seul l'élément racine (tel que purchaseOrder) est global, alors il est simple de n'avoir à qualifier que l'élément racine. Par contre, l'auteur peut savoir que tous les éléments ont été déclarés globalement et qu'ils sont donc tous susceptibles d'être qualifiés, au mieux en profitant d'une déclaration d'espace de noms par défaut pour simplifier la tâche (cette approche est analysée dans le chapitre 3.3). D'un autre côté, si il n'y a pas de motif uniforme entre les déclarations globales et locales, alors l'auteur aura besoin d'avoir une connaissance très précise du schéma pour pouvoir préfixer correctement les éléments et attributs globaux.

3.2 Noms locaux qualifiés

Les éléments et les attributs sont indépendants vis à vis des exigences de qualification bien que nous commencions par décrire la qualification des éléments locaux. Pour spécifier que tous les éléments déclarés localement dans un schéma doivent être qualifiés, on initialise la valeur de elementFormDefault à qualified:

Modifications de po1.xsdpour avoir des noms locaux qualifiés
<schema xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:po="http://www.example.com/PO1"
        targetNamespace="http://www.example.com/PO1"
        elementFormDefault="qualified"
        attributeFormDefault="unqualified">

 <element name="purchaseOrder" type="po:PurchaseOrderType"/>
 <element name="comment"       type="string"/>

 <complexType name="PurchaseOrderType">
  <!-- etc. -->
 </complexType>

 <!-- etc. -->

</schema>

Et dans cette instance de document conforme, nous qualifions tous les éléments explicitement :

Un bon de commande avec des noms locaux qualifiés explicitement  :
<?xml version="1.0"?>
<apo:purchaseOrder xmlns:apo="http://www.example.com/PO1"
                   orderDate="1999-10-20">
    <apo:shipTo country="US">
        <apo:name>Alice Smith</apo:name>
        <apo:street>123 Maple Street</apo:street>
        <!-- etc. -->
    </apo:shipTo>
    <apo:billTo country="US">
        <apo:name>Robert Smith</apo:name>
        <apo:street>8 Oak Avenue</apo:street>
        <!-- etc. -->
    </apo:billTo>
    <apo:comment>Hurry, my lawn is going wild!</apo:comment>
    <!-- etc. -->
</apo:purchaseOrder>

Alternativement, nous pouvons remplacer la qualification explicite de chaque élément par une qualification implicite fournie par un espace de noms par défaut, comme cela est montré ci-dessous dans po2.xml:

Un bon de commande avec des locaux qualifiés par défaut, po2.xml :
<?xml version="1.0"?>
<purchaseOrder xmlns="http://www.example.com/PO1"
               orderDate="1999-10-20">
    <shipTo country="US">
        <name>Alice Smith</name>
        <street>123 Maple Street</street>
        <!-- etc. -->
    </shipTo>
    <billTo country="US">
        <name>Robert Smith</name>
        <street>8 Oak Avenue</street>
        <!-- etc. -->
    </billTo>
    <comment>Hurry, my lawn is going wild!</comment>
    <!-- etc. -->
</purchaseOrder>

Dans po2.xml, tous les éléments de l'instance appartiennent au même espace de noms et la déclaration de l'espace de noms définit un espace de noms par défaut qui s'applique à tous les éléments de l'instance. A partir de là, il est inutile de préfixer explicitement un quelconque élément. Comme autre illustration de l'utilisation d'éléments qualifiés, les schémas du chapitre 5 exigent tous d'utiliser des éléments qualifiés.

La qualification des attributs est très similaire à celle des éléments. Les attributs qui doivent être qualifiés, soit parce qu'ils sont déclarés globalement soit parce que l'attribut attributeFormDefault est initialisé à qualified, sont préfixés dans les instances des documents. Un exemple d'attribut qualifié est l'attribut xsi:nil qui a été introduit au chapitre 2.9. En fait, les attributs qui doivent être qualifiés doivent être explicitement préfixés parce que la spécification XML-Namespaces ne fournit aucun mécanisme pour définir un espace de noms par défaut pour les attributs. Les attributs qui n'ont pas besoin d'être qualifiés apparaissent dans les instances de documents sans préfixe, ce qui est la cas classique.

Le mécanisme de qualification que nous avons décrit jusqu'à maintenant a permis de contrôler toutes les déclarations locales d'éléments et d'attributs à l'intérieur d'un espace de noms cible en particulier. Il est également possible de contrôler la qualification sur une déclaration bien précise en utilisant l'attribut form. Par exemple, pour exiger que l'attribut déclaré localement publicKey soit qualifié dans les instances, nous la déclarons de la manière suivante :

Demande de qualification sur un seul attribut :
<schema xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:po="http://www.example.com/PO1"
        targetNamespace="http://www.example.com/PO1"
        elementFormDefault="qualified"
        attributeFormDefault="unqualified">
 <!-- etc. -->
 <element name="secure">
  <complexType>
   <sequence>
    <!-- élément declarations -->
   </sequence>
   <attribute name="publicKey" type="base64Binary" form="qualified"/>
  </complexType>
 </element>
</schema>

Remarquez que la valeur de l'attribut form écrase la valeur par défaut de l'attribut attributeFormDefault mais uniquement pour l'attribut publicKey. L'attribut form peut tout aussi bien être appliqué à une déclaration d'élément. Une instance de document conforme à ce schéma est par exemple :

Instance ayant un attribut qualifié :
<?xml version="1.0"?>
<purchaseOrder xmlns="http://www.example.com/PO1"
               xmlns:po="http://www.example.com/PO1"
               orderDate="1999-10-20">
    <!-- etc. -->
    <secure po:publicKey="GpM7">
        <!-- etc. -->
    </secure>
</purchaseOrder>

3.3 Déclarations globales versus locales

Quand tous les noms d'éléments sont uniques à l'intérieur d'un espace de noms, les schémas faits à partir de cet espace de noms peuvent ne contenir que des éléments globaux. Cela est similaire dans les faits à l'utilisation de la carte <!ELEMENT> dans une DTD. Dans l'exemple ci-dessous, nous avons modifié la version originale de po1.xsd de telle manière que tous les éléments soient déclarés globalement. Remarquez que nous avons omis dans cet exemple les attributs elementFormDefault et attributeFormDefault pour mettre en valeur le fait que leurs valeurs sont sans intérêt dans ce type de schéma.

Schéma po1.xsd n'utilisant que des déclarations globales d'éléments
<schema xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:po="http://www.example.com/PO1"
        targetNamespace="http://www.example.com/PO1">

 <element name="purchaseOrder" type="po:PurchaseOrderType"/>

 <element name="shipTo"  type="po:USAddress"/>
 <element name="billTo"  type="po:USAddress"/>
 <element name="comment" type="string"/>
 
 <element name="name" type="string"/>
 <element name="street" type="string"/>

 <complexType name="PurchaseOrderType">
  <sequence>
   <element ref="po:shipTo"/>
   <element ref="po:billTo"/>
   <element ref="po:comment" minOccurs="0"/>
   <!-- etc. -->
  </sequence>
 </complexType>

 <complexType name="USAddress">
  <sequence>
   <element ref="po:name"/>
   <element ref="po:street"/>
   <!-- etc. -->
  </sequence>
 </complexType>

 <!-- etc. -->

</schema>

Cette version "globale" po1.xsd validera l'instance po2.xml qui est aussi, comme nous l'avons décrit précédemment, valide par rapport à la version "qualifiée" du schéma, à savoir po1.xsd. En d'autres termes, les deux approches permettent de valider le même document qui utiliserait un espace de noms par défaut. Dans ce sens, elles sont similaires, même si par ailleurs elles sont vraiment différentes. Plus particulièrement, quand tous les éléments sont déclarés globalement, il n'est pas possible de tirer partie des possibilités des noms locaux. Par exemple, vous ne pouvez déclarer qu'un seul élément global appelé title. Par contre, vous pouvez déclarer localement un sous-élément de book appelé title ayant un contenu de type string comme par exemple un deuxième élément title formé de l'énumération des valeurs Mr Mrs Ms.

3.4 Espaces de noms cibles non-déclarés

Au chapitre 2 nous avons expliqué les bases de XML Schema en prenant l'exemple d'un schéma sans déclaration de l'espace de noms cible et d'une instance de document sans déclaration d'espace de noms. La question suivante vient donc naturellement à être posée : Quel est l'espace de noms cible de ces exemples et comment est-il référencé ?

Dans le schéma po.xsd des bons de commande, aucun espace de noms cible ni préfixe (comme po: ci-dessus) n'ont été déclarés qui pourraient nous permettre de faire des références à des types et des éléments du schéma. La conséquence est que les définitions et les déclarations de ce schéma, comme par exemple USAddress et purchaseOrder, sont référencées sans qualification d'espace de noms. En d'autres termes, il n'y un ni préfixe explicite sur les références ni espace de noms implicite sur la référence par défaut. Ainsi, l'élément purchaseOrder est déclaré, dans cet exemple, en utilisant directement une référence non qualifiée au type PurchaseOrderType alors que tous les éléments et les types issus de XML Schema sont explicitement qualifiés par xsd:, préfixe associé à l'espace de noms de XML Schema.

Quand un schéma est conçu sans espace de noms cible, il est fortement recommandé que tous les éléments et types en provenance de l'espace de noms de XML Schema soient explicitement qualifiés par un préfixe tel que xsd:. La raison en est que, si cette association est faite par défaut, les références aux types issus de XML Schema pourront ne pas être distinguées de celles faisant référence aux types définis par l'utilisateur.

Les déclarations d'éléments d'un schéma n'ayant pas d'espace de noms cible sont celles utilisées pour valider les éléments non qualifiés de l'instance de document. Cela étant, elles valident des éléments pour lesquels aucune qualification d'espace de noms n'est fournie ni directement via un préfixe explicite ni indirectement via un préfixe par défaut (xmlns:). Aussi, pour valider un document XML 1.0 qui, typiquement, n'utilise aucun espace de noms, vous devez fournir un schéma n'ayant pas d'espace de noms cible. Comme c'est le cas de la plupart des documents XML 1.0, il y aura beaucoup de schémas écrits sans espace de noms cibles ; vous devez être sûrs de donner à votre programme de traitement un schéma qui corresponde au vocabulaire que vous souhaitez valider.

4. Concepts avancés II : un bon de commande international

Le schéma des bons de commande décrit au chapitre 2 était contenu dans un seul et même document et la plupart de ses constructions -- telles que les déclarations d'éléments et les définitions de types -- furent bâties à partir de rien. En réalité, les auteurs de schémas voudront, pour créer de nouveaux types, pouvoir repartir de constructions existantes, réparties dans plusieurs documents. Dans ce chapitre, nous examinons les mécanismes qui le permettent.

4.1 Un schéma réparti entre plusieurs documents

Au fur et à mesure que les schémas deviennent plus longs, il est souvent préférable de les scinder en plusieurs petits documents, pour en faciliter la maintenance et les conditions d'accès et en augmenter la lisibilité. Pour ces raisons, nous avons isolé les constructeurs des différents types d'adresses du schéma po.xsd et les avons mis dans un nouveau fichier appelé address.xsd. Le schéma ainsi modifié des bons de commande est appelé ipo.xsd:

Le schéma des bons de commande internationaux, ipo.xsd :
<schema targetNamespace="http://www.example.com/IPO"
        xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:ipo="http://www.example.com/IPO">

 <annotation>
  <documentation xml:lang="en">
   schéma des bons de commande internationaux pour Exemple.com
   Copyright 2000 Exemple.com. All rights reserved.
  </documentation> 
 </annotation>

 <!-- include address constructs -->
 <include
  schemaLocation="http://www.example.com/schemas/address.xsd"/>

 <element name="purchaseOrder" type="ipo:PurchaseOrderType"/>

 <element name="comment" type="string"/>

 <complexType name="PurchaseOrderType">
  <sequence>
   <element name="shipTo"     type="ipo:Address"/>
   <element name="billTo"     type="ipo:Address"/>
   <element ref="ipo:comment" minOccurs="0"/>
   <element name="items"      type="ipo:Items"/>
  </sequence>
  <attribute name="orderDate" type="date"/>
 </complexType>

 <complexType name="Items">
  <sequence>
   <element name="item" minOccurs="0" maxOccurs="unbounded">
    <complexType>
     <sequence>
      <element name="productName" type="string"/>
      <element name="quantity">
       <simpleType>
        <restriction base="positiveInteger">
         <maxExclusive value="100"/>
        </restriction>
       </simpleType>
      </element>
      <element name="USPrice"    type="decimal"/>
      <element ref="ipo:comment" minOccurs="0"/>
      <element name="shipDate"   type="date" minOccurs="0"/>
     </sequence>
     <attribute name="partNum" type="ipo:SKU" use="required"/>
    </complexType>
   </element>
  </sequence>
 </complexType>

 <simpleType name="SKU">
  <restriction base="string">
   <pattern value="\d{3}-[A-Z]{2}"/>
  </restriction>
 </simpleType>

</schema>

Le fichier contenant les constructeurs des différents types d'adresses est :

Adresses pour le schéma des bons de commande internationaux, address.xsd :
<schema targetNamespace="http://www.example.com/IPO"
        xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:ipo="http://www.example.com/IPO">

 <annotation>
  <documentation xml:lang="en">
   adresses pour schéma des bons de commande internationaux
   Copyright 2000 Exemple.com. All rights reserved.
  </documentation> 
 </annotation>

 <complexType name="Address">
  <sequence>
   <element name="name"   type="string"/>
   <element name="street" type="string"/>
   <element name="city"   type="string"/>
  </sequence>
 </complexType>

 <complexType name="USAddress">
  <complexContent>
   <extension base="ipo:Address">
    <sequence>
     <element name="state" type="ipo:USState"/>
     <element name="zip"   type="positiveInteger"/>
    </sequence>
   </extension>
  </complexContent>
 </complexType>

 <complexType name="UKAddress">
  <complexContent>
   <extension base="ipo:Address">
    <sequence>
     <element name="postcode" type="ipo:UKPostcode"/>
    </sequence>
    <attribute name="exportCode" type="positiveInteger" fixed="1"/>
   </extension>
  </complexContent>
 </complexType>

 <!-- other Address dérivations pour plus countries --> 

 <simpleType name="USState">
  <restriction base="string">
   <enumeration value="AK"/>
   <enumeration value="AL"/>
   <enumeration value="AR"/>
   <!-- et so on ... -->
  </restriction>
 </simpleType>

 <!-- type simple définition pour UKPostcode -->

</schema>

Les différents constructeurs du schéma des bons de commande et des adresses sont maintenant contenus dans deux fichiers séparés, ipo.xsd et address.xsd. Pour inclure les constructions du deuxième dans le premier, c'est à dire pour les inclure les définitions des types adresse dans l'espace de noms associé aux bons de commande internationaux , l'élément include a été utilisé dans ipo.xsd :

<include schemaLocation="http://www.example.com/schemas/address.xsd"/>

L'effet de cet élément include est d'importer les définitions et les déclarations contenues dans le fichier address.xsd et de les rendre totalement intégrées à l'espace de noms cible du schéma des bons de commande internationaux. L'une des conditions d'utilisation les plus importants de include est que l'espace de noms cible des composants inclus doit être le même que l'espace de noms cible du schéma les incluant, dans notre cas, il s'agit de http://www.example.com/IPO. Importer des définitions et des déclarations en utilisant le mécanisme include ajoute effectivement ces composants à l'espace de noms cible existant. Au chapitre 4.5, nous décrivons un mécanisme complémentaire permettant de modifier les composants au moment de leur importation.

Dans notre exemple, nous n'avons montré l'inclusion que d'un seul document et dans un seul document récepteur. En pratique il est possible d'une part d'inclure plusieurs documents en cumulant plusieurs éléments include et d'autre part d'imbriquer les inclusions, les documents inclus pouvant à leur tour inclure d'autres documents et ainsi de suite. Toutefois, l'imbrication de documents n'est légale que si la condition de base de l'inclusion est vérifiée : toutes les parties incluses du schéma doivent avoir le même espace de noms cible.

Les instances de documents conformes au schéma dont les définitions sont réparties entre plusieurs documents schéma (ndlr : généralement des fichiers contenant les différentes sous-parties constitutives du schéma final) ont seulement besoin de référencer le document schéma principal et l'espace de noms commun ; il est ensuite laissé à la charge du programme de traitement de savoir collecter toutes les définitions spécifiées dans les différents documents schéma inclus. Dans l'exemple ci-dessus, une instance de document ipo.xml (cf chapitre 4.3) référence seulement l'espace de noms cible commun, à savoir http://www.example.com/IPO et (par conséquence) le seul fichier schéma http://www.example.com/schemas/ipo.xsd. Le programme de traitement doit savoir retrouver le document schéma address.xsd à partir du fichier schéma de plus haut niveau.

Au chapitre 5.4, nous décrivons la manière d'utiliser les schémas pour valider un contenu réparti dans plusieurs espaces de noms.

4.2 Dérivation de types par extension

Pour créer nos constructeurs d'adresses, nous avons commencé par créer un type complexe appelé Address selon la règle habituelle (cf address.xsd) et le type Address contient les éléments de base d'une adresse : nom, rue et ville (une telle définition ne marchera pas pour tous les types d'adresses du monde entier mais elle sert le propos de notre exemple). A partir de ce point de départ nous dérivons deux nouveaux types complexes qui contiennent tous les éléments du type original plus des éléments complémentaires spécifiques aux adresses américaines et anglaises. La technique que nous utilisons ici pour dériver ces nouveaux types complexes d'adresses par extension d'un type existant et la même que celle utilisée au chapitre 2.5.1 excepté que notre type de base est ici un type complexe d'être un type simple.

Nous définissons les deux nouveaux types complexes, USAddress et UKAddress, en utilisant l'élément complexType. De plus, nous indiquons que les modèles de contenu des nouveaux types sont eux mêmes de type complexe en utilisant l'élément complexContent (c'est à dire que leurs contenus contiennent des sous-éléments) et nous indiquons qu'il s'agit d'une extension du type de base Address en utilisant l'attribut base de l'élément extension.

Quand un type complexe est étendu, son modèle de contenu effectif est celui du type de base plus celui spécifié dans la dérivation du type. De plus, les deux modèles de contenu sont traités comme deux enfants d'un groupe séquentiel. Dans le cas de UKAddress, le modèle de contenu de UKAddress est celui d'Address augmenté des déclarations de l'élément postcode et de celles de l'attribut exportCode. Cela revient à définir UKAddress à partir de rien comme suit :

 <complexType name="UKAddress">
  <sequence>
   <!-- modèle de contenu de Address -->
   <element name="name"   type="string"/>
   <element name="street" type="string"/>
   <element name="city"   type="string"/>

   <!-- appended élément declaration --> 
   <element name="postcode" type="ipo:UKPostcode"/>
  </sequence> 
                
  <!-- appended attribut declaration --> 
  <attribute name="exportCode" type="positiveInteger" fixed="1"/>
 </complexType>

4.3 Utilisation de types dérivés dans des instances de documents

Dans le scénario qui nous sert d'exemple, les bons de commande sont générés en réponse aux ordres des clients qui peuvent avoir des adresses d'expédition et de facturation différentes. Le bon de commande international, ipo.xml ci-dessous, illustre ce cas où les produits sont expédiés au Royaume-Uni et la facture aux Etats-Unis. Clairement, il serait mieux que le schéma n'ait pas à lister toutes les combinaisons possibles des différents cas d'adresses dans les différents pays du monde et l'idéal serait de pouvoir créer de nouveaux types complexes d'adresses par simple dérivation du type Address.

XML Schema nous permet de définir les éléments billTo et shipTo comme étant de type Address (cf ipo.xsd) et d'utiliser des instances d'adresses internationales à la place des instances d'Address. En d'autres termes, une instance de document dont le contenu est conforme au type UKAddress sera valide si ce contenu apparaît dans le document à un endroit où le type Address était attendu (en supposant que le contenu de UKAddress soit lui même valide). Pour faire marcher cette fonction de XML Schema et pour identifier exactement quel type dérivé est attendu, le type dérivé doit être identifié dans une instance de document : cela se fait en utilisant l'attribut xsi:type qui appartient à l'espace de noms instance de XML Schema. Dans l'exemple, ipo.xml, l'utilisation des types dérivés UKAddress et USAddress est identifiée par le biais des valeurs assignées à l'attribut xsi:type.

div class="exampleOuter">
un bon de commande international, ipo.xml
<?xml version="1.0"?>
<ipo:purchaseOrder
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:ipo="http://www.example.com/IPO"
  orderDate="1999-12-01">

    <shipTo exportCode="1" xsi:type="ipo:UKAddress">
        <name>Helen Zoe</name>
        <street>47 Eden Street</street>
        <city>Cambridge</city>
        <postcode>CB1 1JR</postcode>
    </shipTo>

    <billTo xsi:type="ipo:USAddress">
        <name>Robert Smith</name>
        <street>8 Oak Avenue</street>
        <city>Old Town</city>
        <state>PA</state>
        <zip>95819</zip>
    </billTo>

    <items>
        <item partNum="833-AA">
            <productName>Lapis necklace</productName>
            <quantity>1</quantity>
            <USPrice>99.95</USPrice>
            <ipo:comment>Want this pour the holidays!</ipo:comment>
            <shipDate>1999-12-05</shipDate>
        </item>
    </items>
</ipo:purchaseOrder>

Au chapitre 4.8 nous décrivons comment empêcher cette substitution de type.

4.4 Dérivation de types complexes par restriction

En plus de la dérivation par extension, la dérivation de types complexes peut se faire par restriction des modèles de contenu. La restriction de types complexes est conceptuellement la même que celle des types simples et la différence est qu'elle implique l'utilisation de déclarations de types alors qu'en ce qui concerne la restriction des types simples, il s'agit le plus souvent de réduire la fourchette des acceptables du contenu. Un type complexe dérivé par restriction est très similaire à son type de base, excepté que ses déclarations sont plus limitées que les déclarations du type de base. En fait, les valeurs représentées par le nouveau type sont un sous-ensemble des valeurs représentées par le type de base (comme c'est le cas avec la restriction des types simples). En d'autres termes, une application prévue pour l'ensemble des valeurs du type de base s'exécutera sans difficultés sur les valeurs du type restreint.

Par exemple, supposez que nous souhaitions mettre à jour notre définition de la liste d'items du bon de commande international de telle manière qu'elle doive contenir au moins un item ; le schéma de ipo.xsd permet pour l'instant à l'élément items d'être utilisé sans qu'aucun enfant item soit mis à l'intérieur. Pour créer notre nouveau type ConfirmedItems, nous le définissons de la manière habituelle sauf que nous indiquons qu'il est dérivé par restriction à partir du type de base Items. Nous fixons alors une valeur plus restrictive du nombre d'occurrences minimum du sous-élément item. Remarquez que les types dérivés par restriction reprennent obligatoirement tous les composants de leur définition de base :

Dérivation de ConfirmedItems par restriction à partir de Items
<complexType name="ConfirmedItems">
 <complexContent>
  <restriction base="ipo:Items">
   <sequence>

    <!-- item élément est different than in Items -->
    <element name="item" minOccurs="1" maxOccurs="unbounded">

     <!-- remainder de définition est same comme Items -->
     <complexType>
      <sequence>
       <element name="productName" type="string"/>
       <element name="quantity">
        <simpleType>
         <restriction base="positiveInteger">
          <maxExclusive value="100"/>
         </restriction>
        </simpleType>
       </element>
       <element name="USPrice"    type="decimal"/>
       <element ref="ipo:comment" minOccurs="0"/>
       <element name="shipDate"   type="date" minOccurs="0"/>
      </sequence>
      <attribute name="partNum" type="ipo:SKU" use="required"/>
     </complexType>
    </element>

   </sequence>
  </restriction>
 </complexContent>
</complexType>

Ce changement, qui impose désormais aux instances de documents d'avoir au moins un élément item par élément items, est proche du cas où l'on passe le nombre minimum d'enfants autorisé de 0 à 1. Remarquez que tous les éléments qui auront le type ConfirmedItems seront acceptés comme éléments de type Items (c'est à dire : là où le type items est requis, on peut utiliser un élément de type ConfirmedItems).

Pour expliquer encore plus la restriction, nous donnons dans le tableau 3 des exemples de la manière dont les déclarations d'éléments et d'attributs peuvent être restreintes dans des déclarations de type (le tableau montre des syntaxes de déclaration d'élément quoique les trois premiers exemples puissent également s'appliquer à des restrictions de déclarations d'attributs).

Tableau 3. Exemples de restriction
Base  Restriction Remarques
  default="1" initialisation d'une valeur par défaut lorsque aucune était précédemment donnée
  fixed="100" initialisation d'une valeur fixée lorsque aucune était précédemment donnée
  type="string" spécification d'un type lorsque aucun n'était précédemment donné
(minOccurs, maxOccurs) (minOccurs, maxOccurs)  
(0, 1) (0, 0) exclusion d'un composant optionnel ; cela peut aussi être réalisé en omettant la déclaration du composant de la définition du type réduit
(0, unbounded) (0, 0) (0, 37)  
(1, 9) (1, 8) (2, 9) (4, 7) (3, 3)  
(1, unbounded) (1, 12) (3, unbounded) (6, 6)  
(1, 1) - ne peut pas restreindre plus minOccurs et maxOccurs dans ce cas là

4.5 Redéfinition de types et de groupes

Le chapitre 4.1 décrit la manière d'inclure des définitions et des déclarations réparties dans plusieurs fichiers de schémas mais ayant tous en commun le même espace de noms cible. Le mécanisme include permettait alors d'utiliser "tel-quel" les composants importés de la sorte, en clair, sans aucune modification. Les chapitres suivant expliquaient les dérivations de type par extension et par restriction. Le mécanisme redefine auquel nous allons nous intéresser dans ce chapitre permet combiner l'inclusion et la restriction de manière à pouvoir redéfinir des types simples ou complexes, des groupes et des groupes d'attributs issus de fichiers de schémas externes. Comme pour include, le mécanisme redefine requiert que les composants externes soient dans le même espace de noms cible que le schéma les accueillant, cela étant dit, les composants issus de schémas externes sans espace de noms attribué peuvent également être redéfinis. Dans ce dernier cas, les composants redéfinis font partie intégrante de l'espace de noms cible du schéma les accueillant.

Pour illustrer le mécanisme redefine, nous allons l'utiliser à la place du mécanisme include dans le schéma des bons de commande internationaux, ipo.xsd et cela dans le but de modifier la définition du type complexe Address contenu dans address.xsd :

Utilisation de redefine dans le bon de commande international :
<schema targetNamespace="http://www.example.com/IPO"
        xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:ipo="http://www.example.com/IPO">

 <!-- bring in address constructs -->
 <redefine
  schemaLocation="http://www.example.com/schemas/address.xsd">

  <!-- redéfinition de Address -->
  <complexType name="Address">
   <complexContent>
     <extension base="ipo:Address">
      <sequence>
       <element name="country" type="string"/>
      </sequence>
     </extension>
   </complexContent>
  </complexType>

 </redefine>

 <!-- etc. -->

</schema>

L'élément redefine agit de manière très voisine à celle de l'élément include en intégrant toutes les déclarations et les définitions du fichier address.xsd. La définition du type complexe d'Address utilise la syntaxe d'extension habituelle pour ajouter l'élément country à la définition d'Address. Toutefois, remarquez que le type de base est aussi Address. En dehors de l'élément redefine, toute tentative de définition d'un type complexe de même nom (dans le même espace de noms) que son type de base provoquerait une erreur. Dans le cas présent, il n'y un pas d'erreur et la définition étendue d'Address devient la seule définition d'Address.

Maintenant que le type Address a été redéfini, l'extension s'applique à tous les composants du schéma qui utilisent le type Address. Par exemple, address.xsd contient les définitions de plusieurs variantes internationales d'adresses dérivées du type Address. Ces dérivations reflètent le type redéfini Address, comme cela est montré dans l'extrait suivant :

Extrait de ipo.xml utilisant un type redéfini Address :
 ....
 <shipTo exportCode="1" xsi:type="ipo:UKAddress">
  <name>Helen Zoe</name>
  <street>47 Eden Street</street>
  <city>Cambridge</city>
  <!-- country was added to Address which est base type de UKAddress -->
  <country>United Kingdom</country>
  <!-- postcode was added comme part de UKAddress -->
  <postcode>CB1 1JR</postcode>
 </shipTo>
 ....

Notre exemple a été soigneusement construit de sorte que le type redéfini Address ne soit en conflit d'aucune façon avec les types dérivés de la définition originale du type Address. Mais remarquez qu'un conflit pourrait être facilement être créé. Par exemple, si les dérivations du type adresse internationale avaient étendu Address en lui rajoutant l'élément country, alors la redéfinition du type Address consisterait en un rajout d'un élément du même nom à son modèle de contenu. Or, il est interdit d'avoir deux éléments de même nom (et de même espace de noms cible) et de type différent dans un même modèle de contenu : aussi, la tentative de redéfinition du type Address provoquerait une erreur. En général, redefine ne vous protège pas de telles erreurs et doit être utilisé avec précaution.

4.6 Groupes de substitution

XML Schema fournit un mécanisme, appelé groupes de substitution, qui permet aux éléments d'être substitués par d'autres. Plus précisément, des éléments peuvent être regroupé et déclarés, au niveau du groupe résultant, substituables par un élément dont on précise le nom. Cet élément de substitution est appelé élément de tête et doit être un élément global. Pour illustrer ce propos, nous déclarons deux éléments appelés customerComment et shipComment et on les rattache à un groupe de substitution dont l'élément de tête est comment. De la sorte, customerComment et shipComment deviennent substituables à l'élément comment, en clair, ils peuvent être utilisés à n'importe quel endroit où nous pouvons utiliser comment. Les éléments d'un groupe de substitution doivent avoir le même type que l'élément de tête ou être d'un type dérivé du type de l'élément de tête. Pour déclarer ces deux nouveaux éléments et pour les rendre substituable à l'élément comment, nous utilisons la syntaxe suivante :

Déclaration des éléments substituables pour comment :
<element name="shipComment" type="string"
         substitutionGroup="ipo:comment"/>
<element name="customerComment" type="string"
         substitutionGroup="ipo:comment"/>

Quand ces déclarations sont rajoutées au schéma des bons de commande internationaux, shipComment et customerComment peuvent venir se substituer à l'élément comment dans une instance de document, par exemple :

Extrait de ipo.xml avec éléments de substitution :
....
 <items>
   <item partNum="833-AA">
     <productName>Lapis necklace</productName>
     <quantity>1</quantity>
     <USPrice>99.95</USPrice>
     <ipo:shipComment>
       Use gold wrap si possible
     </ipo:shipComment>
     <ipo:customerComment>
       Want this pour the holidays!
     </ipo:customerComment>
     <shipDate>1999-12-05</shipDate>
   </item>
 </items>
....

Remarquez que lorsqu'une instance de document contient des substitutions d'éléments dont les types sont dérivés de ceux de leur élément de tête, il n'est pas nécessaire d'identifier les types dérivés en utilisant le constructeur xsi:type que nous décrivions au chapitre 4.3.

L'existence d'un groupe de substitution n'exige pas d'utiliser un quelconque des éléments de cette classe, ni ne présume de l'utilisation de l'élément tête. Il fournit simplement un mécanisme pour permettre aux éléments d'être interchangeables.

4.7 Eléments et types abstraits

XML Schema fournit un mécanisme pour forcer la substitution d'un élément ou d'un type en particulier. Quand un élément ou un type est déclaré comme étant "abstrait", il ne peut pas être utilisé dans une instance de document. Quand un élément est abstrait, un membre du groupe de substitution de cet élément doit apparaître dans une instance de document. Quand la définition type correspondant à un élément est déclarée abstraite, toutes les instances de cet élément doivent utiliser le constructeur xsi:type pour faire référence à un type dérivé qui ne soit pas abstrait.

Dans le groupe de substitution exemple que nous décrivions au chapitre 4.6, il serait pratique d'interdire spécifiquement l'utilisation de l'élément comment pour imposer aux instances l'usage des éléments customerComment et shipComment. Pour déclarer que l'élément comment est abstrait, nous modifions sa déclaration originale dans le schéma des bons de commande internationaux, ipo.xsd, comme suit :

<element name="comment" type="string" abstrait="true"/>

Avec comment déclaré comme abstrait, les instances des bons de commande internationaux sont maintenant valident que si elles contiennent les éléments customerComment et shipComment.

Déclarer un élément comme étant abstrait requiert l'utilisation d'un groupe de substitution. Déclarer un type comme étant abstrait requiert simplement l'utilisation, dans les instances de documents, d'un type qui lui soit dérivé (alors identifié par l'attribut xsi:type). Considérez la définition de schéma suivante :

Schéma pour véhicules :
<schema xmlns="http://www.w3.org/2001/XMLSchema" 
         targetNamespace="http://cars.example.com/schema" 
         xmlns:target="http://cars.example.com/schema"> 

 <complexType name="Vehicle" abstrait="true"/> 

 <complexType name="Car"> 
  <complexContent>
   <extension base="target:Vehicle"/>
  </complexContent>
 </complexType>

 <complexType name="Plane"> 
  <complexContent>
   <extension base="target:Vehicle"/>
  </complexContent>
 </complexType>

 <element name="transport" type="target:Vehicle"/> 
</schema>

L'élément transport n'est pas abstrait, en conséquence il peut apparaître dans les instances de documents. Toutefois, parce que sa définition de type est abstraite, il ne pourrait pas apparaître dans une instance de document sans référence à un type dérivé via l'attribut xsi:type. Cela signifie que l'extrait suivant n'est pas valide par rapport au schéma :

<transport xmlns="http://cars.example.com/schema"/>

parce que le type de l'élément transport est abstrait. Par contre, cet autre fragment est valide :

 <transport xmlns="http://cars.example.com/schema"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:type="Car"/>

parce qu'il utilise un type non-abstrait qui est substituable pour Vehicle.

4.8 Contrôler la création et l'utilisation de types dérivés

Jusqu'à maintenant, nous avons été capable de dériver de nouveaux types et de les utiliser dans les instances de documents sans aucune restriction. En réalité, les auteurs de schémas voudront parfois contrôler les dérivations de certains types en particulier et l'utilisation de types dérivés dans les instances.

XML Schema fournit un couple de mécanismes qui contrôle la dérivation des types. L'un de ces mécanismes permet à l'auteur du schéma de spécifier qu'un type complexe en particulier ne peut faire l'objet de types dérivés, ni (a) par restriction, ni (b) par extension, ou (c) du tout. Pour illustrer ce propos, supposons que nous voulions interdire toute dérivation du type Address par restriction parce que nous avons l'intention de ne l'utiliser que comme type de base que pour des types étendus tels que USAddress et UKAddress. Pour interdire ce mode de dérivation, nous modifions légèrement la définition originale du type Address comme suit :

Interdire les dérivations par restriction du type Address :
<complexType name="Address" final="restriction">
 <sequence>
  <element name="name"   type="string"/>
  <element name="street" type="string"/>
  <element name="city"   type="string"/>
 </sequence>
</complexType>

La valeur restriction de l'attribut final empêche les dérivations par restriction. Empêcher toute dérivation ou n'empêcher que les dérivations par extension se traduit respectivement par les valeurs #all et extension. De plus, il est possible d'utiliser l'attribut finalDefault au niveau de l'élément schema permettant d'imposer un mode de dérivation à toutes les définitions de type et des déclarations d'éléments du schéma. L'attribut finalDefault peut prendre les mêmes valeurs que l'attribut final.

Un autre mécanisme de dérivation de type permet de contrôler les facettes autorisées dans la dérivation de nouveaux types simples. Quand un type simple est défini, l'attribut fixed peut être appliqué à n'importe laquelle de ses facettes pour en empêcher la modification lors d'une dérivation. Par exemple, nous pouvons définir un type simple Postcode comme :

Empêcher les changements de facettes d'un type simple :
<simpleType name="Postcode">
  <restriction base="string">
    <length value="7" fixed="true"/>
  </restriction>
</simpleType>

Une fois le type simple défini de la sorte, nous pouvons le dériver pour créer un nouveau type de code postal auquel on pourra appliquer une modification d'une facette déclarée non fixée dans la définition de base du type, par exemple :

Dérivation autorisée du type Postcode :
<simpleType name="UKPostcode">
  <restriction base="ipo:Postcode">
    <pattern value="[A-Z]{2}\d\s\d[A-Z]{2}"/>
  </restriction>
</simpleType>

Mais il serait impossible de dériver un nouveau type de code postal dans lequel nous tenterions de modifier l'une quelconque des facettes fixées dans la définition de base :

Dérivation interdite du type Postcode :
<simpleType name="UKPostcode">
 <restriction base="ipo:Postcode">
  <pattern value="[A-Z]{2}\d\d[A-Z]{2}"/>
  <!-- illegal attempt to modify facet fixed in base type --> 
  <length value="6" fixed="true"/>
 </restriction>
</simpleType>

En plus des mécanismes de contrôle des dérivations de type, XML Schema fournit un mécanisme de contrôle de l'utilisation des dérivations et groupes de substitution dans les instances de documents. Au chapitre 4.3, nous décrivons comment les types dérivés, USAddress et UKAddress, pouvaient être utilisés par les éléments shipTo et billTo dans les instances de documents. Ces types dérivés peuvent remplacer le modèle de contenu fourni par le type Address parce qu'ils sont dérivés du type Address. Toutefois, le remplacement par des types dérivés peut être contrôlé en utilisant l'attribut block dans une définition de type. Par exemple, si nous voulons bloquer l'utilisation de toute dérivation par restriction à la place du type Address (peut être pour la même raison que celle qui nous fait définir Address avec final="restriction"), nous pouvons modifier la définition originale d'Address comme suit :

Empêcher les dérivations par restriction du type Address dans l'instance :
<complexType name="Address" block="restriction">
 <sequence>
  <element name="name"   type="string"/>
  <element name="street" type="string"/>
  <element name="city"   type="string"/>
 </sequence>
</complexType>

La valeur restriction de l'attribut block empêche que les dérivations par restriction remplacent Address dans une instance de document. Toutefois, cela n'empêcherait pas UKAddress et USAddress de remplacer Address parce que ces types étaient dérivés par extension. Empêcher complètement le remplacement par des types dérivés, ou seulement par ceux dérivés par extension, serait indiqué respectivement par les valeurs #all et extension. Comme avec final, il possible d'utiliser avec l'élément schema l'attribut blockDefault qui permet d'appliquer globalement ces contrôles à l'ensemble des définitions de types et déclarations d'éléments du schéma.

5. Concepts avancés III : un rapport trimestriel

Les applications de dépôt de commande d'achat et de facturation sont susceptibles de donner lieu à une production de rapports synthétisant le nombre de produits vendus par région. Un exemple d'un tel rapport, couvrant la période du quatrième trimestre de l'année 1999, se trouve dans le fichier 4Q99.xml.

Remarquez que dans ce chapitre nous qualifions les éléments dans le schéma et utilisons des éléments non qualifiés dans les instances, en clair des espaces de noms par défaut (quand cela est possible).

Rapport trimestriel, 4Q99.xml
<purchaseReport
  xmlns="http://www.example.com/Report"
  period="P3M" periodEnding="1999-12-31">

 <regions>
  <zip code="95819">
   <part number="872-AA" quantity="1"/>
   <part number="926-AA" quantity="1"/>
   <part number="833-AA" quantity="1"/>
   <part number="455-BX" quantity="1"/>
  </zip>
  <zip code="63143">
   <part number="455-BX" quantité="4"/>
  </zip>
 </regions>

 <parts>
  <part number="872-AA">Lawnmower</part>
  <part number="926-AA">Baby Monitor</part>
  <part number="833-AA">Lapis Necklace</part>
  <part number="455-BX">Sturdy Shelves</part>
 </parts>

</purchaseReport>

Le rapport liste, par nombre et quantité, les pièces facturées dans différents endroits reconnus par leur code zip et fournit une description de chaque pièce. En résumant les données de facturation, l'intention du rapport est claire et les données ne sont pas ambiguës parce qu'un nombre de contraintes sont à l'oeuvre. Par exemple, chaque code zip apparaît seulement une seule fois (contrainte d'unicité). De même, la description des pièces facturées n'apparaît qu'une seule fois même si les pièces ont pu être facturées à plusieurs codes zip différents (contrainte référentielle), regardez par exemple la pièce numéro 455-BX. Dans les chapitres suivant, nous verrons comment spécifier ces contraintes en utilisant XML Schema.

Le schéma du rapport, report.xsd :
<schema targetNamespace="http://www.example.com/Report"
        xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:r="http://www.example.com/Report"
        xmlns:xipo="http://www.example.com/IPO"
        elementFormDefault="qualified">

 <!-- pour SKU -->
 <import namespace="http://www.example.com/IPO"/>

 <annotation>
  <documentation xml:lang="en">
   Report schema for Example.com
   Copyright 2000 Example.com. All rights reserved.
  </documentation> 
 </annotation>

 <element name="purchaseReport">
  <complexType>
   <sequence>
    <element name="regions" type="r:RegionsType">
     <keyref name="dummy2" refer="r:pNumKey">
      <selector xpath="r:zip/r:part"/>
      <field xpath="@number"/>
     </keyref>
    </element>

    <element name="parts" type="r:PartsType"/>
   </sequence>
   <attribute name="period"       type="duration"/>
   <attribute name="periodEnding" type="date"/>
  </complexType>
  
  <unique name="dummy1">
   <selector xpath="r:regions/r:zip"/>
   <field xpath="@code"/>
  </unique>

  <key name="pNumKey">
   <selector xpath="r:parts/r:part"/>
   <field xpath="@number"/>
  </key>
 </element>

 <complexType name="RegionsType">
  <sequence>
   <element name="zip" maxOccurs="unbounded">
    <complexType>
     <sequence>
      <element name="part" maxOccurs="unbounded">
       <complexType>
        <complexContent>
         <restriction base="anyType">
          <attribute name="number"   type="xipo:SKU"/>
          <attribute name="quantity" type="positiveInteger"/>
         </restriction>
        </complexContent>
       </complexType>
      </element>
     </sequence>
     <attribute name="code" type="positiveInteger"/>
    </complexType>
   </element>
  </sequence>
 </complexType>

 <complexType name="PartsType">
  <sequence>
   <element name="part" maxOccurs="unbounded">
    <complexType>
     <simpleContent>
      <extension base="string">
       <attribute name="number" type="xipo:SKU"/>
      </extension>
     </simpleContent>
    </complexType>
   </element>
  </sequence>
 </complexType>

</schema>

5.1 Spécification d'unicité

XML Schema permet de spécifier la contrainte d'unicité de toute valeur d'attribut ou d'élément à l'intérieur d'un périmètre défini. Pour indiquer que la valeur d'un attribut ou d'un élément en particulier est unique, nous utilisons l'élément unique. Il permet d'une part de sélectionner un ensemble d'éléments et ainsi de définir le périmètre d'applicabilité de la contrainte d'unicité et d'autre part d'identifier le "champ" de l'attribut ou de l'élément qui doit être unique à l'intérieur du périmètre défini. Dans le cas du schéma de notre rapport, report.xsd, l'attribut xpath de l'élément selector contient une expression XPath qui est regions/zip qui retourne la liste de tous les éléments zip d'une instance du rapport. De même, l'attribut xpath de l'élément field contient une seconde expression XPath, @code, qui spécifie que les valeurs de l'attribut code des éléments retournés doivent être uniques. Remarquez comment les expressions XPath limitent la portée de ce qui doit être unique. En effet, le rapport peut contenir un autre attribut code mais cette valeur ne sera pas prise en compte dans le calcul d'unicité puisqu'elle réside à l'extérieur du périmètre défini par la première expressions XPath. Remarquez aussi que les expressions XPath que vous pouvez utiliser dans l'attribut xpath sont limitées à un sous-ensemble de l'ensemble du langage XPath défini dans XML Path Language 1.0. (remarque de traduction : une version française de cette recommandation existe également).

Nous pouvons aussi indiquer des combinaisons de champs qui doivent être uniques. Pour illustrer ce propos, supposez que nous pouvons relâcher la contrainte d'unicité sur les codes zip bien que nous souhaitions conserver la contrainte d'unicité des produits par code zip. Nous pourrions atteindre cet objectif en spécifiant qu'un couple formé du code zip et du numéro de produit doit être unique. D'après le document rapport 4Q99.xml, les valeurs combinées du code zip et du numéro de produit seraient : {95819 872-AA}, {95819 926-AA}, {95819 833-AA}, {95819 455-BX}, et {63143 455-BX}. En clair, ces couples ne font pas la distinction entre les combinaisons des codes zip et des numéros d'article obtenus à partir d'une ou plusieurs listes de codes zip spécifiés et la présence d'un produit vendu plus d'une fois pour un même code zip serait listée de manière non équivoque (c'est à dire plusieurs fois). En d'autres termes, un programme de traitement du schéma serait capable de détecter les violations de la contrainte d'unicité.

Pour définir des combinaisons de valeurs, nous ajoutons simplement des éléments field pour identifier toutes les valeurs impliquées. Aussi, pour ajouter le numéro d'article sans doublon à notre définition actuelle, nous ajoutons un nouvel élément field dont la valeur de l'attribut xpath qui est part/@number. La définition résultante sélectionne les élément zip enfants des éléments regions différents pas leurs code puis les éléments part enfants des éléments zip différents par la valeur de leur attribut number :

Une valeur unique composée :
 <unique name="dummy1">
  <selector xpath="r:regions/r:zip"/>
  <field    xpath="@code"/>
  <field    xpath="r:part/@number"/>
 </unique>

5.2 Définition des clés et de leurs références

Dans le rapport des ventes trimestrielles de 1999, la description de chaque pièce facturée n'apparaît qu'une fois. Nous pourrions renforcer cette contrainte en utilisant l'élément unique mais nous souhaitons aussi garantir la présence d'une description de pièce pour chaque couple pièce-quantité listé sous un code zip. Nous renforçons la contrainte en utilisant les éléments key et keyref. Le schéma du rapport, report.xsd, montre que les constructions key et keyref sont appliquées en utilisant presque la même syntaxe que unique. L'élément clé s'applique à la valeur de l'attribut number des éléments part, enfants de l'élément parts. Le fait de déclarer que l'attribut number est une clé signifie que sa valeur doit être unique et ne peut pas être initialisée à nil (c'est à dire qu'elle est forcément renseignée) et le nom associé à la clé, pNumKey, la rend référençable de n'importe où.

Pour garantir que les couples pièce-quantité font référence à des descriptions de pièces, nous spécifions que l'attribut number (<field>@number</field>) est une référence (keyref) à pNumKey qui est une clé (key). Ainsi faite, la déclaration de number signifie que lorsque cet attribut est utilisé dans une instance de document, sa valeur doit être égale à celle d'un pNumKey. La valeur de l'attribut clé (pNumKey) doit être unique mais elle peut être référencée par plusieurs attributs de type keyref comme par exemple number. (note de la traduction française : le mécanisme décrit ici ne garantit pas que la référence faite à la description soit la bonne).

Comme vous pouvez vous en douter par analogie avec l'élément unique, il est possible de définir des combinaisons des valeurs de key et keyref. En utilisant ce mécanisme, nous pourrions assez facilement aller plus loin en exigeant que les numéros d'articles soient égaux et en définissant une combinaison de valeurs qui doivent être égales. Les valeurs dont on parle peuvent être des combinaisons de plusieurs types de valeurs (string, integer, date, etc.) à condition que l'ordre et le type des références de l'élément field soient identiques dans les deux définitions de key et de keyref.

5.3 Contraintes de XML Schema par rapport aux attributs ID de XML 1.0

XML 1.0 fournit un mécanisme de contrôle d'unicité via les attributs de type ID, IDREF et IDREFS. Il existe aussi dans XML Schema au travers des types simples ID, IDREF, et IDREFS qui permettent de déclarer des attributs de type XML 1.0. Mais XML Schema introduit des mécanismes complémentaires plus souples et plus puissants. Par exemple, les règles d'unicité peuvent être appliquée à tout contenu d'élément ou d'attribut, quelqu'en soit leurs types. A l'inverse, ID est un type de la déclaration attribute et ne peut s'appliquer aux attributs (ndlr : la phrase semble être une erreur mais c'est écrit tel quel dans le texte original anglais), aux éléments ou à leurs contenus. XML Schema permet de spécifier le périmètre de confinement de l'unicité alors que celui d'un ID est toujours le document dans sa totalité. Finalement, XML Schema permet de créer des types key et keyref en relation avec le contenu des éléments et des attributs alors que ID ne propose pas ces facilités.

5.4 Importation de types

Le schéma du rapport, report.xsd, fait appel au type simple appelé xipo:SKU, défini dans un autre schéma et dans un autre espace de noms cible. Nous rappelons que nous avons utilisé include pour que le schéma ipo.xsd intègre les définitions et des déclarations de address.xsd. Ici, nous ne pouvons pas utiliser include puisque include ne s'applique qu'à des schémas externes de même espace de noms cible. Il s'ensuit que l'élément include ne permet pas d'identifier des espaces de noms cibles spécifiques (bien que ce mécanisme ait besoin d'un schemaLocation). Le mécanisme d'import que nous décrivons dans ce chapitre est important car il permet aux composants de schémas issus de différents espaces de noms cibles d'être utilisés ensemble. Cela offre la possibilité de valider des contenus d'instances de documents écrites avec des composants définis à travers plusieurs espaces de noms.

Pour importer le type SKU et l'utiliser dans le schéma du rapport, nous déclarons l'espace de noms dans lequel SKU est défini et l'associons à un préfixe à utiliser dans le schéma du rapport. Concrètement, nous utilisons l'élément import pour identifier l'espace de noms cible de SKU, http://www.example.com/IPO et nous l'associons au préfixe xipo au moyen d'une déclaration standard d'espace de noms. Le type simple SKU, défini dans l'espace de noms http://www.example.com/IPO, peut ensuite être référencé comme xipo:SKU dans toutes les définitions et déclarations du schéma du rapport.

Dans notre exemple, nous importons un type simple à partir d'un espace de noms externe et l'utilisons dans des déclarations d'attributs. XML Schema permet d'importer plusieurs composants d'un schéma, issus de plusieurs espaces de noms différents qui peuvent ensuite être référencés à partir des définitions et des déclarations. Par exemple dans report.xsd nous pourrions réutiliser l'élément comment déclaré dans ipo.xsd en le référençant à l'aide de la déclaration suivante :

<element ref="xipo:comment"/>

Remarquez toutefois que nous ne pouvons pas réutiliser l'élément shipTo de po.xsd, et le cas suivant est illégal parce que seuls les composants d'un schéma global peuvent être importés :

<element ref="xipo:shipTo"/>

Dans ipo.xsd, l'élément comment est déclaré globalement, en d'autres termes il est déclaré comme un élément directement fils de l'élément racine schema. Par contre, shipTo est déclaré localement, en clair il est déclaré à l'intérieur une définition de type complexe, en l'occurrence le type PurchaseOrderType.

Les types peuvent aussi être importés et être utilisés comme types de base pour dériver de nouveaux types. Seuls les types complexes nommés peuvent être importés ; les types locaux définis anonymement ne peuvent pas être importés. Supposez que nous voulions inclure dans nos rapports le nom d'un analyste et ses coordonnées pour le contacter. Nous pouvons réutiliser le type complexe (défini globalement) USAddress de address.xsd et l'étendre afin de définir un nouveau type appelé Analyst qui contiendra les deux nouveaux éléments phone et email :

Définition du nouveau type Analyst par extension de USAddress
<complexType name="Analyst">
 <complexContent>
  <extension base="xipo:USAddress">
   <sequence>
    <element name="phone" type="string"/>
    <element name="email" type="string"/>
   </sequence>
  </extension>
 </complexContent>
</complexType>

Avec ce nouveau type, nous pouvons déclarer un élément appelé analyst dans la déclaration de l'élément purchaseReport (ces déclarations ne sont pas données en exemple) dans le schéma du rapport. L'instance de document suivante sera conforme au schéma ainsi modifié :

instance de document conforme au schéma de rapport avec un type Analyst
<purchaseReport
  xmlns="http://www.example.com/Report"
  period="P3M" periodEnding="1999-12-31">
  <!-- regions et parts éléments omitted -->
   <analyst>
        <name>Wendy Uhro</name>
        <street>10 Corporate Towers</street>
        <city>San Jose</city>
        <state>CA</state>
        <zip>95113</zip>
        <phone>408-271-3366</phone>
        <email>uhro@exemple.com</email>
   </analyst>
</purchaseReport>

Quand les composants d'un schéma proviennent de plusieurs espaces de noms, chacun doit être identifié par un élément import distinct. Les éléments import eux-mêmes doivent apparaître comme étant les premiers enfants de l'élément schema. En plus, chaque espace de noms doit être associé à un préfixe utilisé pour qualifier les références aux composants des schéma importés. Finalement, les éléments import peuvent recevoir l'attribut schemaLocation pour donner la localisation des ressources associées aux espaces de noms. Cet attribut est détaillé plus loin.

5.4.1 Bibliothèques de types

Au fur et à mesure que XML schemas deviendra plus largement utilisé, les auteurs de schémas voudront créer des types simples et complexes qui puissent être partagés et utilisés entre différents schemas. XML Schemas fournit déjà des types qui jouent ce rôle, en particulier, les types décrits dans l'annexe des types simples et dans la présentation des bibliothèques de types.

Les auteurs de schémas voudront, à n'en pas douter, créer leurs propres bibliothèques de types pour représenter par exemple des monnaies, des unités de mesure, des listes d'adresses professionnelles etc. Chaque bibliothèque peut consister en un schéma contenant une ou plusieurs définitions, par exemple, celle d'un type currency :

Exemple de type currency dans une bibliothèque de types :
<schema targetNamespace="http://www.example.com/Currency"
        xmlns:c="http://www.example.com/Currency"
        xmlns="http://www.w3.org/2001/XMLSchema">

 <annotation>
  <documentation xml:lang="en">
   Definition of Currency type based on ISO 4217
  </documentation> 
 </annotation>

 <complexType name="Currency">
  <simpleContent>
   <extension base="decimal">
    <attribute name="name">
     <simpleType>
      <restriction base="string">
      
        <enumeration value="AED">
         <annotation>
          <documentation xml:lang="en">
           United Arab Emirates: Dirham (1 Dirham = 100 Fils)
          </documentation>
         </annotation>
        </enumeration>
      
        <enumeration value="AFA">
         <annotation>
          <documentation xml:lang="en">
           Afghanistan: Afghani (1 Afghani = 100 Puls)
          </documentation>
         </annotation>
        </enumeration>
      
        <enumeration value="ALL">
         <annotation>
          <documentation xml:lang="en">
           Albania, Lek (1 Lek = 100 Qindarka)
          </documentation>
         </annotation>
        </enumeration>
      
        <!-- et other currencies -->

      </restriction>      
     </simpleType>
    </attribute>
   </extension>
  </simpleContent>
 </complexType>

</schema>

Exemple d'un élément apparaissant dans une instance et ayant ce type :

<convertFrom name="AFA">199.37</convertFrom>

Une fois le type currency défini, il peut être disponible pour une réutilisation dans d'autres schémas via le mécanisme import qui vient juste d'être décrit.

5.5 Eléments et attributs any

Dans les chapitres précédents nous avons vu plusieurs mécanismes permettant d'étendre les modèles de contenu des types complexes. Par exemple, un modèle de contenu mixte peut contenir un mélange de caractères de données et d'éléments mais un modèle de contenu peut également contenir des éléments dont les types sont issus d'espaces de noms externes. Ces mécanismes offrent respectivement des contraintes très lâches ou très strictes. Le but de ce chapitre est de décrire un mécanisme souple qui permette aux modèles de contenu d'être étendus par n'importe quel élément et attribut des espaces de noms spécifiés.

Pour illustrer ce propos, considérez une version du rapport trimestriel 4Q99html.xml, dans laquelle nous avons embarqué une représentation HTML des données XML des pièces. Le contenu HTML apparaît comme contenu de l'élément htmlExemple et l'espace de noms par défaut est changé pour l'élément HTML de plus haut niveau (l'élément table) de telle sorte que tous les éléments HTML appartiennent à l'espace de noms de HTML, http://www.w3.org/1999/xhtml:

Rapport trimestriel avec HTML, 4Q99html.xml
<purchaseReport
  xmlns="http://www.example.com/Report"
  period="P3M" periodEnding="1999-12-31">

 <regions>
   <!-- part sales listed par zip code, data from 4Q99.xml -->
 </regions>

 <parts>
   <!-- part descriptions from 4Q99.xml -->
 </parts>

 <htmlExemple>
  <table xmlns="http://www.w3.org/1999/xhtml"
         border="0" width="100%">
   <tr>
     <th align="left">Zip Code</th>
     <th align="left">Part nombre</th>
     <th align="left">quantité</th>
   </tr>
   <tr><td>95819</td><td> </td><td> </td></tr>
   <tr><td> </td><td>872-AA</td><td>1</td></tr>
   <tr><td> </td><td>926-AA</td><td>1</td></tr>
   <tr><td> </td><td>833-AA</td><td>1</td></tr>
   <tr><td> </td><td>455-BX</td><td>1</td></tr>
   <tr><td>63143</td><td> </td><td> </td></tr>
   <tr><td> </td><td>455-BX</td><td>4</td></tr>
  </table>
 </htmlExemple>

</purchaseReport>

Pour autoriser l'apparition des balises HTML dans les instances de rapports nous en modifions le schéma en déclarant un nouvel élément htmlExemple dont le contenu est défini par l'élément any. En général, un élément any spécifie que tout fragment XML bien formé est autorisé comme modèle de contenu du type. Dans l'exemple, nous demandons au XML d'appartenir à l'espace de noms http://www.w3.org/1999/xhtml, en d'autres termes, il doit être HTML. L'exemple requiert via les valeurs de minOccurs et maxOccurs, qu'il y ait au moins un élément de cet espace de noms.

Modification de la déclaration de l'élément purchaseReport pour autoriser l'usage de HTML dans l'instance :
<element name="purchaseReport">
 <complexType>
  <sequence>
   <element name="regions" type="r:RegionsType"/>
   <element name="parts"   type="r:PartsType"/>
   <element name="htmlExemple">
    <complexType>
     <sequence>
      <any namespace="http://www.w3.org/1999/xhtml"
           minOccurs="1" maxOccurs="unbounded"
           processContents="skip"/>
     </sequence> 
    </complexType>
   </element>
  </sequence>
  <attribute name="period"       type="duration"/>
  <attribute name="periodEnding" type="date"/>
 </complexType>
</element>

La modification permet aux fragments XML bien formés de l'espace de noms http://www.w3.org/1999/xhtml d'apparaître à l'intérieur de l'élément htmlExemple. Par conséquent 4Q99html.xml est admis parce qu'il contient un élément qui (avec ses enfants) est bien formé, l'élément apparaît à l'intérieur de l'élément approprié (htmlExemple) et l'instance de document affirme que l'élément et son contenu appartiennent à l'espace de noms requis. Toutefois, le fragment HTML qui s'y trouve peut ne pas être valide parce que rien dans l'instance 4Q99html.xml ne peut intrinsèquement le garantir. Si cette garantie est nécessaire, la valeur de l'attribut processContents doit être initialisé à strict (la valeur par défaut). Dans ce cas, le programme de traitement de l'instance XML est obligé d'obtenir le schéma associé à l'espace de noms requis (http://www.w3.org/1999/xhtml) et de valider le contenu HTML apparaissant à l'intérieur de l'élément htmlExemple.

Dans l'exemple suivant, nous définissons un type text similaire au type text défini dans la présentation de la bibliothèque de types de XML Schema (cf le chapitre 5.4.1) qui convient pour du texte internationalisé lisible par un oeil humain. Le nouveau type text permet d'avoir un mélange d'éléments et de caractères de données sans restriction, de n'importe quel espace de noms, comme par exemple des annotations Ruby, parallèlement à l'utilisation de l'attribut optionnel xml:lang. La valeur lax de l'attribut processContents dit au programme de traitement de l'instance XML de valider le contenu de l'élément sur la base d'un "peut-le-faire" : il validera les éléments et les attributs pour lesquels il peut obtenir l'information de schéma, mais il ne signalera pas d'erreur pour ceux dont il ne peut pas obtenir une quelconque information de schéma.

Exemple de type text :
<xsd:complexType name="text">
 <xsd:complexContent mixed="true">
  <xsd:restriction base="xsd:anyType">
   <xsd:sequence>
    <xsd:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
   </xsd:sequence>
   <xsd:attribute ref="xml:lang"/>
  </xsd:restriction>
 </xsd:complexContent>
</xsd:complexType>

Les espaces de noms peuvent être utilisés pour permettre et interdire le contenu de l'élément de différentes manières en fonction de la valeur de l'attribut namespace, comme cela est montré dans le tableau 4 :

Tableau 4. Attribut namespace dans any
Value de l'attribut namespace Contenu autorisé de l'élément
##any Tout fragment XML bien formé de n'importe quel espace de noms (cas par défaut)
##local Tout fragment XML bien formé qui n'est pas qualifié, c'est à dire qui ne soit pas déclaré être dans un espace de noms
##other Tout fragment XML bien formé qui n'est pas de l'espace de noms cible du type en train d'être défini
"http://www.w3.org/1999/xhtml ##targetNamespace" Tout fragment XML bien formé appartenant à n'importe quel espace de noms de la liste (dont les items sont séparés par des blancs) ; ##targetNamespace est un raccourci pour l'espace de noms cible du type en train d'être défini

En plus de l'élément any qui autorise un contenu d'élément en fonction des espaces de noms, il y a un élément correspondant anyAttribute qui autorise les attributs d'apparaître dans des éléments. Par exemple, nous pouvons permettre à tout attribut HTML d'apparaître dans l'élément htmlExemple en rajoutant anyAttribute à sa déclaration :

Modification de la déclaration htmlExemple pour autoriser l'utilisation des attributs HTML :
Titre exemple
<element name="htmlExemple">
 <complexType>
  <sequence>
   <any namespace="http://www.w3.org/1999/xhtml"
        minOccurs="1" maxOccurs="unbounded"
        processContents="skip"/>
  </sequence>
  <anyAttribute namespace="http://www.w3.org/1999/xhtml"/>
 </complexType>
</element>

Cette déclaration permet à un attribut HTML, disons href, d'apparaître dans l'élélment htmlExemple. Par exemple :

Un attribut HTML dans l'élément htmlExemple :
....
  <htmlExemple xmlns:h="http://www.w3.org/1999/xhtml"
               h:href="http://www.example.com/reports/4Q99.html">
     <!-- HTML markup here -->
  </htmlExemple>
....

L'attribut namespace de l'élément anyAttribute peut être prendre n'importe laquelle des valeurs listée pour l'élément any dans le tableau 4 et anyAttribute peut être qualifié par l'attribut processContents. En opposition à un élément any, l'élément anyAttribute ne peut pas contraindre le nombre d'attributs qui peut apparaître dans un élément.

5.6 attribut schemaLocation

XML Schema utilise les attributs schemaLocation et xsi:schemaLocation dans trois cas de figures.

1. dans une instance de document, l'attribut xsi:schemaLocation fournit une indication de l'auteur au programme de traitement concernant l'emplacement des documents schéma. L'auteur garantit que les schéma mentionnés sont corrects pour contrôler, espace de noms par espace de noms, la validité du contenu du document. Par exemple, nous pouvons indiquer l'emplacement du schéma du rapport à un programme de traitement du rapport trimestriel :

Utilisation de l'attribut schemaLocation dans le rapport trimestriel, 4Q99html.xml
<purchaseReport
  xmlns="http://www.example.com/Report"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.example.com/Report
  http://www.example.com/Report.xsd"
  period="P3M" periodEnding="1999-12-31">

 <!-- etc. -->

</purchaseReport>

L'attribut schemaLocation contient des pairs de valeurs : le premier membre de chaque paire est l'espace de noms dont le second membre est l'emplacement recommandé où trouver le schéma approprié. La présence de ces recommandations n'impose au programme de traitement ni qu'il puisse réellement accéder au schémas mentionnés ni qu'il les exploite. Le programme de traitement est libre d'utiliser d'autres schémas obtenus par tout moyen à sa convenance ou de ne pas utiliser de schéma du tout.

Un schéma n'est pas obligé d'avoir un espace de noms (cf chapitre 3.4). L'attribut noNamespaceSchemaLocation sert alors à fournir aux programmes de traitement des informations sur les emplacements des schémas qui n'ont pas d'espace de noms cible.

2. Dans un schéma, l'élément include a un attribut obligatoire, schemaLocation, dont la valeur est une URI de référence qui doit identifier un document schéma. L'effet est de construire un schéma final effectif en fusionnant les déclarations et les définitions des schémas appelant et appelé. Par exemple, au chapitre 4, les définitions des types Address, USAddress, UKAddress, USState (complétées de leurs déclarations d'attributs et d'éléments locaux respectives) du schéma address.xsd ont été ajoutées aux déclarations d'éléments de purchaseOrder et comment, et aux définitions de PurchaseOrderType, Items et SKU (aussi complétées de leurs déclarations d'attributs et d'éléments locaux) de ipo.xsd pour former un seul schéma.

3. Dans un schéma, l'élément import a aussi des attributs optionnels namespace et schemaLocation. L'attribut schemaLocation a la même signification que l'attribut xsi:schemaLocation expliqué en (1). Plus particulièrement, il fournit une recommandation de l'auteur quant à l'emplacement du document schéma dont l'auteur garantit qu'il fournit les composants requis pour l'espace de noms identifié par l'attribut namespace. Pour importer des composants qui sont dans aucun espace de noms cible, l'élément import , avec ou sans attribut schemaLocation, sera utilisé sans attribut namespace. Les références aux composants importés de la sorte sont non qualifiées.

Remarquez que l'attribut schemaLocation ne fournit qu'un conseil et certains programmes de traitements et applications auront raison de ne pas exploiter cette donnée. Par exemple, un éditeur HTML peut avoir un schéma HTML intégré.

5.7 Conformité

une instance de document peut être contrôlée vis à vis d'un schéma pour vérifier si les règles qui y sont spécifiées sont appliquées dans l'instance. Ce traitement fait classiquement deux choses, (1) il contrôle la conformité aux règles, processus appelé validation du schéma et (2) il ajoute des informations supplémentaires qui ne sont pas présentes originellement dans l'instance, comme par exemple des types et des valeurs par défaut, et qui sont appelées informations de contribution.

L'auteur d'une instance de document, un bon de commande par exemple, peut réclamer dans l'instance elle-même, qu'elle se conforme aux règles d'un schéma en particulier. L'auteur le fait en utilisant l'attribut schemaLocation discuté ci-dessus. Mais indépendamment de la présence ou non de l'attribut schemaLocation, une application est libre de traiter un document au regard de n'importe quel schéma. Par exemple, une application de gestion des achats peut avoir comme politique d'utiliser toujours le même schéma de bon de commande, cela indépendamment de toute valeur de l'attribut schemaLocation.

Le contrôle de conformité peut être représenté comme procédant étape par étape, contrôlant en premier que l'élément racine du instance de document a les bons contenus, puis contrôlant que chaque sous-élément soit conforme à sa description dans un schéma et ainsi de suite jusqu'à ce que tout le document soit vérifié. Les programmes de traitement doivent rapporter ce que le contrôle a permis de vérifier.

Pour contrôler la conformité d'un élément, le programme de traitement commence par identifier la déclaration de l'élément dans un schéma puis contrôle que l'attribut targetNamespace du schéma corresponde à l'URI de l'espace de noms de l'élément. Une autre solution serait de déterminer que le schéma n'a pas d'attribut targetNamespace et que l'élément instancié n'est pas qualifié par un préfixe d'espace de noms.

En supposant que les espaces de noms correspondent, le programme de traitement examine ensuite le type de l'élément, soit tel qu'il est donné par la déclaration qui se trouve dans le schéma soit via la présence d'un attribut xsi:type dans l'instance. Dans le dernier cas, le type instancié doit être une substitution autorisée du type donné dans le schéma ; ce qui est autorisé dépend de l'attribut block de la déclaration de l'élément. Arrivé à ce stade, les valeurs par défaut et d'autres informations de contribution sont appliquées.

Ensuite, le programme de traitement contrôle les attributs et les contenus immédiats de l'élément, les comparant avec les attributs et contenus autorisés par le type de l'élément. Par exemple, considérons un élément shipTo identique à celui du chapitre 2.1, le programme de traitement contrôle ce qui est autorisé par le modèle Address, type de l'élément shipTo.

Si l'élément a un type simple, le programme de traitement vérifie que l'élément n'a pas d'attribut et ne contient pas lui même d'autres éléments et que les caractères qu'il contient correspondent au règles du type simple concerné. Cela implique parfois de contrôler la séquence de caractères vis à vis d'expressions régulières ou d'énumérations et aussi parfois de contrôler que la séquence de caractères représente une valeur autorisée de la fourchette de valeurs spécifiée.

Si l'élément a un type complexe, alors le programme de traitement contrôle que les attributs obligatoires sont présents, que leurs valeurs sont conformes aux exigences de leurs types. Il contrôle aussi que tous les sous-éléments obligatoires sont présents et que la séquence des sous-éléments (et tout contenu mixte) est conforme au modèle de contenu déclaré du type complexe concerné. En ce qui concerne les sous-éléments, les schémas peuvent soit exiger qu'il y ait une correspondance exacte des noms, soit autoriser la substitution par un élément équivalent ou par tout élément autorisé suite à l'utilisation de la particule 'any'.

A moins qu'un schéma n'indique le contraire (comme cela est possible avec la particule 'any'), le contrôle de conformité rentre ensuite dans les niveaux plus bas en s'intéressant aux sous-éléments, l'un après l'autre, répétant pour chacun l'opération décrite ci-dessus.


A Remerciements

Beaucoup de personnes ont contribué par des idées, de la matière et des remarques à l'élaboration de ce document, ce qui en a considérablement amélioré la qualité. En particulier, l'éditeur met en exergue les apports de David Beech, Paul Biron, Don Box, Allen Brown, David Cleary, Dan Connolly, Roger Costello, Martin Dürst, Martin Gudgin, Dave Hollander, Joe Kesselman, John McCarthy, Andrew Layman, Eve Maler, Ashok Malhotra, Noah Mendelsohn, Michael Sperberg-McQueen, Henry Thompson, Misha Wolf, et Priscilla Walmsley pour la validation des exemples cités.

B Types simples et leurs facettes

Les valeurs légales de chaque type simple peuvent être contraintes par l'application d'une ou plusieurs facettes. Les tableaux B1.a et B1.b listent tous les types simples pré-définis de XML Schema et les facettes applicables à chacun. Les noms des types simples et les facettes sont liées entre les tableaux et leurs descriptions correspondantes dans XML Schema Partie 2 : types de données

Tableau B1.a. Types simples et facettes applicables
Types simples Facettes
  length minLength maxLength pattern enumeration whiteSpace
string y y y y y y
normalizedString y y y y y y
token y y y y y y
byte       y y y
unsignedByte       y y y
base64Binary y y y y y
hexBinary y y y y y y
integer       y y y
positiveInteger       y y y
negativeInteger       y y y
nonNegativeInteger       y y y
nonPositiveInteger       y y y
int       y y y
unsignedInt       y y y
long       y y y
unsignedLong       y y y
short       y y y
unsignedShort       y y y
decimal       y y y
float       y y y
double       y y y
boolean       y   y
time       y y y
dateTime       y y y
duration       y y y
date       y y y
gMonth       y y y
gYear       y y y
gYearMonth       y y y
gDay       y y y
gMonthDay       y y y
Name y y y y y y
QName y y y y y y
NCName y y y y y y
anyURI y y y y y y
language y y y y y y
ID y y y y y y
IDREF y y y y y y
IDREFS y y y   y y
ENTITY y y y y y y
ENTITIES y y y   y y
NOTATION y y y y y y
NMTOKEN y y y y y y
NMTOKENS y y y   y y

Les facettes listées dans le tableau B1.b ne s'appliquent qu'à des types simples ordonnés. Comme cela n'est pas applicable à tous les types simples, ce deuxième tableau ne contient qu'un sous-ensemble de la liste des types simples.

Tableau B1.b. Types simples et facettes applicables
Simple Types Facets
  max
Inclusive
max
Exclusive
min
Inclusive
min
Exclusive
totalDigits fractionDigits
byte y y y y y y
unsignedByte y y y y y y
integer y y y y y y
positiveInteger y y y y y y
negativeInteger y y y y y y
nonNegativeInteger y y y y y y
nonPositiveInteger y y y y y y
int y y y y y y
unsignedInt y y y y y y
long y y y y y y
unsignedLong y y y y y y
short y y y y y y
unsignedShort y y y y y y
decimal y y y y y y
float y y y y    
double y y y y    
time y y y y    
dateTime y y y y    
duration y y y y    
date y y y y    
gMonth y y y y    
gYear y y y y    
gYearMonth y y y y    
gDay y y y y    
gMonthDay y y y y    

C Utilisation des entités

XML 1.0 fournit différents types d'entités qui sont des fragments de contenu étiquetés qui peuvent être utilisé tant pour l'écriture de DTD (les entités paramètre) que les instances de documents. Au chapitre 2.7, nous expliquons comment des groupes nommés offrent une fonctionnalité voisine de celle offerte par les entités paramètres. Dans ce chapitre nous montrons comment les entités peuvent être déclarées dans les instances de documents et comment les équivalents fonctionnels des entités peuvent être déclarés dans les schémas.

Supposez que nous voulions déclarer et utiliser un entité dans une instance de document et que le document soit aussi contraint par un schéma. Par exemple :

Déclarer et référencer une entité dans une instance de document.
<?xml version="1.0" ?>
<!DOCTYPE PurchaseOrder [
<!ENTITY eacute "é">
]>
<purchaseOrder xmlns="http://www.example.com/PO1"
               orderDate="1999-10-20>
 <!-- etc. --> 
  <city>Montr&eacute;al</city>
 <!-- etc. -->
</purchaseOrder>

Ici, nous déclarons une entité appelée eacute dans un sous-ensemble local au document de la DTD (c'est à dire dans le prologue du document) et nous référençons ensuite cette entité dans le contenu de l'élément city. Remarquez que, quand cette instance de document sera traitée, l'entité sera dé-référencée (c'est à dire résolue) avant que la validation de la conformité de l'instance par rapport au schéma ait lieu. En d'autres termes, un programme de conformité déterminera la validité de l'élément city en utilisant Montréal comme contenu de l'élément.

Nous pouvons aboutir à une approche similaire sans toutefois être identique en déclarant dans le schéma un élément dont le contenu sera défini de manière appropriée comme suit :

<xsd:element name="eacute" type="xsd:token" fixed="é"/>

Cet élément peut être utilisé dans une instance de document de la manière suivante :

Utilisation d'élément à la place d'une entité dans une instance de document.
<?xml version="1.0" ?>
<purchaseOrder xmlns="http://www.example.com/PO1"
               xmlns:c="http://www.example.com/characterLes éléments"
               orderDate="1999-10-20>
 <!-- etc. --> 
  <city>Montr<c:eacute/>al</city>
 <!-- etc. -->
</purchaseOrder>

Dans ce cas, un programme de validation traitera deux éléments, un élément city et un élément eacute pour lequel le programme de traitement fournira le caractère é. Remarquez que le rajout de cet élément compliquera les applications de recherche de chaînes de caractères ; les deux formes du nom "Montréal" données dans les deux exemples ci-dessus ne se trouveront pas mutuellement en utilisant les techniques standard de comparaison de chaînes de caractères.

D Expressions régulières

La facette pattern de XML Schema utilise le langage des expressions régulières qui supporte Unicode. Il est totalement décrit dans XML Schema tome 2. Le langage est similaire à celui utilisé dans le langage de programmation Perl, bien que les expressions soient mises en correspondance avec une représentation lexicale complète plutôt qu'au travers d'une représentation du niveau utilisateur comme c'est le cas par exemple avec les notions de ligne et de paragraphe. Pour cette raison, le langage d'expression ne contient pas les métacaractères ^ et $, bien que ^ soit utilisé pour exprimer les exclusions, par exemple [^0-9]x.

Table D1. Exemples d'expressions régulières
Expression Exemples de correspondance(s)
chapitre \d chapitre 0, chapitre 1, chapitre 2 ....
chapitre\s\d chapitre suivi par un seul caractère espace blanc (espace, tabulation, retour à la ligne, etc.) suivi par un seul chiffre
chapitre\s\w chapitre suivi par un seul caractère espace blanc (espace, tabulation, retour à la ligne, etc.), suivi par un caractère de mot (Chiffre ou lettre tel que défini dans XML 1.0)
Espan&#xF1;ola Española
\p{Lu} tout caractère majuscule, la valeur de \p{} (par exemple "Lu") est défini par Unicode
\p{IsGreek} tout caractère grec, la forme 'Is' peut être appliquée à tout nom (par exemple "Greek") tel que défini par Unicode
\P{IsGreek} tout caractère non grec, la forme 'Is' peut être appliqué à tout nom (par exemple "Greek") tel que défini par Unicode
a*x x, ax, aax, aaax ....
a?x ax, x
a+x ax, aax, aaax ....
(a|b)+x ax, bx, aax, abx, bax, bbx, aaax, aabx, abax, abbx, baax, babx, bbax, bbbx, aaaax ....
[abcde]x ax, bx, cx, dx, ex
[a-e]x ax, bx, cx, dx, ex
[-ae]x -x, ax, ex
[ae-]x ax, ex, -x
[^0-9]x tout caractère autre qu'un chiffre suivi du caractère x
\Dx tout caractère autre qu'un chiffre suivi du caractère x
.x tout caractère suivi du caractère x
.*abc.* 1x2abc, abc1x2, z3456abchooray ....
ab{2}x abbx
ab{2,4}x abbx, abbbx, abbbbx
ab{2,}x abbx, abbbx, abbbbx....
(ab){2}x ababx

E Index

Index des éléments de XML Schema. Chaque nom d'élément est lié à une description XML formelle soit dans le tome "Structures" soit dans le tome "Types de données" de la spécification XML Schema. Les noms des éléments sont suivis d'un plusieurs liens vers les exemples (identifiés par les numéros de chapitre où ils se trouvent) de cette introduction.

Index des attributs de XML Schema. Chaque nom d'attribut est suivi par une ou plusieurs paires de références. Chacune est composée d'un lien vers un des exemples de ce tome et d'un lien vers la description XML formelle se trouvant soit dans le tome "Structures" soit le tome "Types de données"(Datatypes) de la spécification XML Schema.

Les types simples de XML Schema sont décrits dans le tableau 2.